1002:Redraw Beautiful Drawings
最大流。。。。用sap+gap优化的模版过的。。。
1.
2.
3.
跑一遍最大流。
假设流量小于总权值和,那么说明impossible。
假设等于:
构建残图网络。假设残图网络能够形成一条回路,那么说明有多解。
#include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include<queue> using namespace std; #define INF 99999999 const int maxn =810; const int maxm =2*410*410+410*4; const int oo = 1<<29; struct Arclist { int cnt, head[maxn], dis[maxn]; int cur[maxn], pre[maxn], gap[maxn], aug[maxn]; int mp[maxn][maxn]; int vis[maxn]; int vis2[maxn]; struct node { int u, v, w, next; }edge[maxm]; void init() { cnt = 0; memset(head,-1,sizeof(head)); } void add(int u, int v, int w) { edge[cnt].u = u; edge[cnt].v = v; edge[cnt].w = w; edge[cnt].next = head[u]; head[u] = cnt++; edge[cnt].u = v; edge[cnt].v = u; edge[cnt].w = 0; edge[cnt].next = head[v]; head[v] = cnt++; } int sap(int s, int e, int n) { int max_flow = 0, u = s; int mindis; for(int i = 0; i <= n; i++) { cur[i] = head[i]; dis[i] = 0; gap[i] = 0; } aug[s] = oo; pre[s] = -1; gap[0] = n; while(dis[s]<n) { bool flag = false; if(u==e) { max_flow += aug[e]; for(int v = pre[e]; v != -1; v = pre[v]) { int id = cur[v]; edge[id].w -= aug[e]; edge[id^1].w += aug[e]; aug[v] -= aug[e]; if(edge[id].w==0) u = v; } } for(int id = cur[u]; id != -1; id = edge[id].next) { int v = edge[id].v; if(edge[id].w>0 && dis[u]==dis[v]+1) { flag = true; pre[v] = u; cur[u] = id; aug[v] = std::min(aug[u], edge[id].w); u = v; break; } } if(flag==false) { if(--gap[dis[u]]==0) break; mindis = n; cur[u] = head[u]; for(int id = head[u]; id != -1; id = edge[id].next) { int v = edge[id].v; if(edge[id].w>0 && dis[v]<mindis) { mindis = dis[v]; cur[u] = id; } } dis[u] = mindis+1; ++gap[dis[u]]; if(u!=s) u = pre[u]; } } return max_flow; } int n,m,k; int sou(int pre,int x,int leap) { vis2[x]=1; if(leap==0) { for(int i=n+1;i<=m+n;i++) { if(i==pre)continue; if(mp[x][i]==0)continue; if(vis2[i]) { vis2[x]=0; return 1; } if(sou(x,i,1)){ vis2[x]=0; return 1; } } } if(leap==1) { for(int i=1;i<=n;i++) { if(i==pre)continue; if(mp[x][i]==0)continue; if(vis2[i]){ vis2[x]=0; return 1; } if(sou(x,i,0)){ vis2[x]=0; return 1; } } } vis2[x]=0; return 0; } int dfs() { memset(vis,0,sizeof(vis)); memset(vis2,0,sizeof(vis2)); for(int i=1;i<=n;i++) { if(vis[i])continue; if(sou(-1,i,0))return 1; } return 0; } void pan() { memset(mp,0,sizeof(mp)); for(int i=0;i<cnt;i++) { int u=edge[i].u; int v=edge[i].v; int w=edge[i].w; if(u>n)continue; if(v<=n||v>n+m)continue; mp[u][v]=w; mp[v][u]=k-w; } if(dfs()) { cout<<"Not Unique"<<endl; return ; } cout<<"Unique"<<endl; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(j!=1)cout<<" "; printf("%d",k-mp[i][j+n]); } cout<<endl; } } }G; int a[510]; int b[510]; int main() { int m,n,k; while(~scanf("%d%d%d",&n,&m,&k)) { int st=n+m+1; int ed=n+m+2; G.init(); int ans=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); G.add(st,i,a[i]); ans+=a[i]; } for(int i=n+1;i<=n+m;i++) { scanf("%d",&b[i]); G.add(i,ed,b[i]); } for(int i=1;i<=n;i++) { for(int j=n+1;j<=n+m;j++) { G.add(i,j,k); } } int mx; mx=G.sap(st,ed,n+m+2); if(mx<ans)cout<<"Impossible"<<endl; else { G.n=n; G.m=m; G.k=k; G.pan(); } } return 0; }
1003:Scary Path Finding Algorithm
由题意可知,直接构造即可。。。
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<stdlib.h> #include<vector> #include<cmath> #include<queue> #include<set> using namespace std; void dos() { int a[31]; a[0]=1; for(int i=1; i<=30; i++) { a[i]=a[i-1]*2; } int n=30*2+1; int m=30*3-3; cout<<n<<" "<<m<<endl; for(int i=1; i<=29; i++) { printf("%d %d %d ",i,i+30,0); printf("%d %d %d ",i,i+1,-a[30-i]); printf("%d %d %d ",i+30,i+1,-a[30-i+1]); } } long long spfa_slf() { int n,m; cin >> n >> m; vector<pair<int,int> > edges[111]; for(int i = 0; i < m; i++) { int x,y,w; cin >> x >> y >> w; edges[x].push_back(make_pair(y,w)); } deque<int> q; vector<long long> dist(n+1, ~0ULL>>1); vector<bool> inQueue(n+1, false); dist[1] = 0; q.push_back(1); inQueue[1] = true; int doge = 0; while(!q.empty()) { int x = q.front(); q.pop_front(); if(doge++ > 23333333) { puts("doge"); return 233; } for(vector<pair<int,int> >::iterator it = edges[x].begin(); it != edges[x].end(); ++it) { int y = it->first; int w = it->second; if(dist[y] > dist[x] + w) { dist[y] = dist[x] + w; if(!inQueue[y]) { inQueue[y] = true; if(!q.empty() && dist[y] > dist[q.front()]) q.push_back(y); else q.push_front(y); } } } inQueue[x] = false; } return dist[n]; } int main() { int n; // freopen("data.in","r",stdin); while(~scanf("%d",&n)) { dos(); } // spfa_slf(); // cout<<"-00"<<endl; return 0; }