Central Europe Regional Contest 2012 Problem J: Conservation
题目不难,感觉像是一个拓扑排序,要用双端队列来维护;
要注意细节,不然WA到死 = =!
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #define maxn 100005 5 using namespace std; 6 7 int q[2*maxn],count[2][maxn],tail,head,n,m,in[maxn]; 8 vector<int>ve[maxn]; 9 10 int solve(int lab) 11 { 12 head=tail=n; 13 int cnt=0,cc=0,f=lab; 14 for(int i=1;i<=n;i++) 15 if(count[2-lab][i]==0&&in[i]==lab){q[tail++]=i;cnt++;} 16 if(cnt==0)return -1; 17 for(int i=1;i<=n;i++) 18 if(count[2-lab][i]==0&&in[i]!=lab){q[tail++]=i;} 19 while(head<tail) 20 { 21 int v=q[head++]; 22 if(in[v]!=f){f=in[v];cc++;} 23 int l=ve[v].size(); 24 for(int i=0;i<l;i++) 25 { 26 count[2-lab][ve[v][i]]--; 27 if(count[2-lab][ve[v][i]]==0) 28 { 29 if(in[v]==in[ve[v][i]]) 30 q[--head]=ve[v][i]; 31 else q[tail++]=ve[v][i]; 32 } 33 } 34 } 35 return cc; 36 } 37 38 int main() 39 { 40 int t,x,y; 41 scanf("%d",&t); 42 while(t--) 43 { 44 scanf("%d%d",&n,&m); 45 for(int i=1;i<=n;i++)ve[i].clear(); 46 memset(count,0,sizeof count); 47 for(int i=1;i<=n;i++)scanf("%d",&in[i]); 48 for(int i=1;i<=m;i++) 49 { 50 scanf("%d%d",&x,&y); 51 ve[x].push_back(y); 52 count[0][y]++; 53 count[1][y]++; 54 } 55 x=solve(1); 56 y=solve(2); 57 if(x<0||y<0)printf("%d\n",max(x,y)); 58 else printf("%d\n",min(x,y)); 59 } 60 return 0; 61 }