1. 程式人生 > >題解:[SCOI2011]糖果

題解:[SCOI2011]糖果

依舊是比較明顯的差分約束

注意對於五種操作分別對應的連邊方式

然後注意head的初始值判斷,要不然總是超時……今天遇到好幾次了

建圖時加個小剪枝,否則會TLE

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 using namespace std;
 7 const int m=100020;
 8 const int inf=0x3f3f3f3f;
9 int head[m], dis[m], used[m]; 10 bool vis[m]; 11 long long ans; 12 int k, n; 13 int cnt; 14 queue<int> q; 15 struct Edge{ 16 int to, w, next; 17 }e[m*4]; 18 void add(int u,int v,int w){ 19 cnt++; 20 e[cnt].next=head[u]; 21 e[cnt].w=w; 22 e[cnt].to=v; 23 head[u]=cnt;
24 } 25 bool spfa(){ 26 while(!q.empty()){ 27 int u=q.front(); 28 q.pop(); 29 vis[u]=false; 30 used[u]=0; 31 for(int i=head[u]; i; i=e[i].next){ 32 int v=e[i].to; 33 int w=e[i].w; 34 if(dis[v]<dis[u]+w){ 35 dis[v]=dis[u]+w;
36 used[i]++; 37 if(used[i]==n) return false;//判斷是否有環 38 if(!vis[v]){ 39 q.push(v); 40 vis[v]=true; 41 } 42 } 43 } 44 } 45 return true; 46 } 47 int main(){ 48 scanf("%d%d",&n,&k); 49 for(int i=1; i<=k; i++) { 50 int c, u, v; 51 scanf("%d%d%d",&c,&u,&v); 52 if(c==1){ 53 add(u,v,0); 54 add(v,u,0); 55 } 56 if(c==2) add(u,v,1); 57 if(c==3) add(v,u,0); 58 if(c==4) add(v,u,1); 59 if(c==5) add(u,v,0); 60 if(c%2==0 && u==v){ 61 printf("-1\n"); 62 return 0; 63 } 64 } 65 for(int i=1; i<=n; i++) { 66 vis[i]=1; 67 dis[i]=1; 68 used[i]=1; 69 q.push(i); 70 } 71 if(!spfa()){ 72 printf("-1\n"); 73 return 0; 74 } 75 for(int i=1; i<=n; i++) 76 ans+=dis[i]; 77 printf("%lld\n",ans); 78 return 0; 79 }