[cogs736][网络流24题#13]星际转移[网络流,网络判定]
将一个空间站分为天数个点,每次枚举天数,每增加一天就把对应天数的边连上,用网络流判定可行性,即-判断最大流是否不小于k,注意编号不要错位。通过此题,可见一些网络流题目需要用到网络判定方法,但虽然答案具有单调性,却不适合二份答案,原因有两个:一是网络流题目一般数据规模不会很大,二是网络流题目如果二分就必须每次全部重新建图,而普通枚举可以在上以阶段的图中递推操作,所以往往枚举的效率和代码复杂度更好。
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cmath> 7 #include <ctime> 8 #include <queue> 9 10 using namespace std; 11 12 #define INF 0x3f3f3f3f 13 14 template<const int _n> 15 struct Edge 16 { 17 struct Edge_base { int to,w,next; }e[_n]; 18 int cnt,p[_n]; 19 Edge() { clear(); } 20 void clear() { cnt=1,memset(p,0,sizeof(p)); } 21 int start(const int x) { return p[x]; } 22 Edge_base& operator[](const int x) { return e[x]; } 23 void insert(const int x,const int y,const int z) 24 { e[++cnt].to=y; e[cnt].next=p[x]; e[cnt].w=z; p[x]=cnt; return ; } 25 }; 26 27 int n,m,SSS,TTT,Flow; 28 int level[5100],cur[5100],h[5100]; 29 vector<int> vec[5100]; 30 Edge<210000> e; 31 32 bool Bfs(const int S) 33 { 34 int i,t; 35 queue<int> Q; 36 memset(level,0,sizeof(level)); 37 level[S]=1; 38 Q.push(S); 39 while(!Q.empty()) 40 { 41 t=Q.front(),Q.pop(); 42 for(i=e.start(t);i;i=e[i].next) 43 { 44 if(!level[e[i].to] && e[i].w) 45 { 46 level[e[i].to]=level[t]+1; 47 Q.push(e[i].to); 48 } 49 } 50 } 51 return level[TTT]; 52 } 53 54 int Dfs(const int S,const int bk) 55 { 56 if(S==TTT)return bk; 57 int rest=bk; 58 for(int &i=cur[S];i;i=e[i].next) 59 { 60 if(level[e[i].to]==level[S]+1 && e[i].w) 61 { 62 int flow=Dfs(e[i].to,min(rest,e[i].w)); 63 e[i].w-=flow; 64 e[i^1].w+=flow; 65 if((rest-=flow)<=0)break; 66 } 67 } 68 if(rest==bk)level[S]=0; 69 return bk-rest; 70 } 71 72 int Dinic() 73 { 74 while(Bfs(SSS)) 75 { 76 memcpy(cur,e.p,sizeof(cur)); 77 Flow+=Dfs(SSS,0x3f3f3f3f); 78 } 79 return Flow; 80 } 81 82 int P(const int x,const int y) 83 { 84 return y*n+x; 85 } 86 87 int main() 88 { 89 freopen("home.in","r",stdin); 90 freopen("home.out","w",stdout); 91 int i,j,t,k,c; 92 93 scanf("%d%d%d",&n,&m,&k); 94 for(i=1;i<=m;++i) 95 { 96 scanf("%d%d",&h[i],&t); 97 for(j=1;j<=t;++j) 98 { 99 scanf("%d",&c); 100 if(c==-1)c=n+1;if(c==0)c=n+2; 101 vec[i].push_back(c); 102 if(j!=1)e.insert(vec[i][j-2],vec[i][j-1],1); 103 } 104 e.insert(vec[i][t-1],vec[i][0],i); 105 } 106 107 SSS=n+2,TTT=n+1; 108 n+=2; 109 int S=n,T=n-1; 110 if(!Bfs(SSS)){printf("0\n");goto End;} 111 112 e.clear();SSS=1000,TTT=SSS+1; 113 e.insert(SSS,P(S,0),INF);e.insert(P(S,0),SSS,0); 114 e.insert(P(T,0),TTT,INF);e.insert(TTT,P(T,0),0); 115 for(i=1;;i++) 116 { 117 e.insert(SSS,P(S,i),INF); 118 e.insert(P(S,i),SSS,0); 119 e.insert(P(T,i),TTT,INF); 120 e.insert(TTT,P(T,i),0); 121 for(j=1;j<=n;++j) 122 { 123 e.insert(P(j,i-1),P(j,i),INF); 124 e.insert(P(j,i),P(j,i-1),0); 125 } 126 for(j=1;j<=m;++j) 127 { 128 e.insert(P(vec[j][(i-1)%vec[j].size()],i-1),P(vec[j][i%vec[j].size()],i),h[j]); 129 e.insert(P(vec[j][i%vec[j].size()],i),P(vec[j][(i-1)%vec[j].size()],i-1),0); 130 } 131 if(Dinic()>=k)break; 132 } 133 134 printf("%d\n",i); 135 136 End: 137 return 0; 138 }