I have done a lot about this kind of questions, and I will try again to write my network stream linked list.
I have been confused about this question for a long time.
Question:
There are M rooms, now you want to protect room N, room number is [0, M-1]. At first, all the doors in the room are open, and the control panel of the door is in the room. That is to say, if the room can control several corresponding doors, from this room, you can go to other rooms through these doors. If the control panel is in another room, this door cannot be opened in this room.
What is required now is to close the minimum door so that the room to be protected is not infiltrated.
Ideas:
First, simplify the model, regardless of the control relationship. That is to say, the door is bidirectional. Then the door can be opened from both sides, and the two rooms are connected with an edge with a capacity of 1, which indicates the capacity to close the door.
This is a very naked cutting edge model.
Now, we add another condition to control the relationship. If U controls the V door, this door will not be cut in any case, because it cannot be closed. Once the flow, is uncontrollable.
So U has an edge to V, and the capacity is INF. V has a side with a capacity of 1 to U, which indicates the cost from opening the door to closing the door.
That's all you need to do. Max stream = min cut...
Wait... the most amazing thing is that I have cut the edge ....
Find the number of augmented rails... it's no wonder that something is wrong ....
#include<iostream>#include<cstdlib>#include<cstdio>#define NV 55#define NE 999#define INF 0x7FFFFFFF#define eps 1e-8#define CC(a) memset(a,0,sizeof(a))#define FF(i,N) for( int i=0;i<N;i++ )template<class T> inline void checkmin( T &a,T b ){ if( a>b||a==-1 ) a=b; }using namespace std;int M,N,s,t,alloc;struct edge{ int u,v,c,f,next;}E[NE];int gap[NV],dis[NV],cur[NV],pre[NV],flag[NV],head[NV];void addEdge( int u,int v,int c,int cc=0 ){ E[alloc].u=u; E[alloc].v=v; E[alloc].c=c; E[alloc].next=head[u]; head[u]=alloc++; E[alloc].u=v; E[alloc].v=u; E[alloc].c=cc;E[alloc].next=head[v]; head[v]=alloc++;}void setG(){ CC(E);alloc=0; memset( head,-1,sizeof(head) ); char str[11];int n,v; scanf( "%d%d",&M,&N ); s=0;t=M+1; addEdge( N+1,t,INF ); FF( i,M ) { /**printf( "1\n" );/**/ scanf( "%s %d",&str,&n ); if( str[0]=='I' ) addEdge(s,i+1,INF); while( n-- ) { scanf( "%d",&v ); addEdge( i+1,v+1,INF,1 ); //addEdge( v+1,i+1,1,1 ); } }/*** FF(i,alloc) printf( "u:%d v:%d c:%d next:%d\n",E[i].u,E[i].v,E[i].c,E[i].next );/***/}int sap(){ CC(gap),CC(dis); for( int i=0;i<=t;i++ ) cur[i]=head[i]; int u=pre[s]=s,maxflow=0,aug=-1; gap[0]=t+1; while( dis[s]<=t ){loop: for( int &i=cur[u];i!=-1;i=E[i].next ) { int v=E[i].v; if( E[i].c-E[i].f&&dis[u]==dis[v]+1 ){ pre[v]=u; checkmin(aug,E[i].c-E[i].f); u=v; if( v==t ) { maxflow+=aug; for( u=pre[u];v!=s;v=u,u=pre[u] ) E[cur[u]].f+=aug,E[cur[u]^1].f-=aug; aug=-1; } goto loop; } } int mind=t; for( int i=head[u];i!=-1;i=E[i].next ) { int v=E[i].v; if( E[i].c-E[i].f&&mind>dis[v] ) cur[u]=i,mind=dis[v]; } if( --gap[dis[u]]==0 ) break; gap[dis[u]=mind+1]++; u=pre[u]; } return maxflow;}void dfss( int cur ){ flag[cur]=1; for( int i=head[cur];i!=-1;i=E[i].next ) if( !flag[E[i].v]&&E[i].c-E[i].f ) dfss(E[i].v);}void dfst( int cur ){ flag[cur]=2; for( int i=head[cur];i!=-1;i=E[i].next ) if( !flag[E[i].v]&&E[i].c-E[i].f ) dfst(E[i].v);}int main(){ int T; scanf( "%d",&T ); while( T-- ) { setG(); int maxflow=sap(); /**printf("maxflow:%d\n",maxflow);/**/ if( maxflow==INF ){ printf( "PANIC ROOM BREACH\n" ); continue; } CC(flag); dfss(s),dfst(t);/*** for( int i=0;i<=t;i++ ) printf( "%d ",flag[i] );/***/ int sum=0; for( int i=0;i<alloc;i++ ) if( flag[E[i].u]==1&&flag[E[i].v]==2&&E[i].c==E[i].f ) sum++; printf( "%d\n",sum ); } return 0;}