题意:有n个人坐在圆桌上,每个人带着糖果若干,每次只能给旁边的人1科糖果,而且坐相邻的两个人最多只能给一次(要么你给我,要么我给你),问是否能将糖果平均分了。
思路:明显每个人最多只能多于平均值2个糖果,因为他只能分别往左和右边的人给1颗。而多于平均值1的人可以任意选1个方向,只要到最后所有人满足了即可。多余糖果超过3的、平均数是浮点型的都是无解。
在第i和第i+1个人之间建两条边(即无向边拆成2条有向边),分别从一方指向另一方。1和n也建两条。分两步:
(1)将持有2个多余糖果的人先处理,用DFS分别向左边和右边各深搜1次,直到遇到缺糖的人,若成功,则标记走过的路径。
(2)将持有1个多余糖果的人先左边尝试给别人糖果,遇到标记的边则返回,从另一个方向尝试给别人糖果。
若以上都成功了,那么糖果就能成功平均分配。但是可能会将两条边都同时标记了,那么他们互相抵消了,比如3 1 1 3 四个人。那么如果,1沿着1-2-3给了3一个糖果,而4沿着4->3>2给了2一个糖果,那么就成功了,而他们走过的边也互相抵消了,即2-3和3-2抵消了,相当于1只走到2,而4只走到3。这一步只需要在输出答案时处理一下即可。
这样的思路也WA???????????
1 #include <bits/stdc++.h> 2 #define INF 0x7f7f7f7f 3 #define pii pair<int,int> 4 #define LL long long 5 using namespace std; 6 const int N=101000; 7 struct node 8 { 9 int from,to; 10 bool vis; 11 node(){}; 12 node(int from,int to,bool vis):from(from), to(to), vis(vis){}; 13 }edge[N*20]; 14 int edge_cnt, candy[N], even; 15 vector<int> vect[N]; 16 17 18 void add_node(int from,int to) 19 { 20 edge[edge_cnt]=node(from, to, 0); 21 vect[from].push_back(edge_cnt++); 22 } 23 24 bool cansolve(int n, LL sum) //是否有解 25 { 26 if(sum%n>0) return false; 27 for(int i=1; i<=n; i++) if( abs(candy[i]-even )>2 ) return false; 28 return true; 29 } 30 31 bool DFS(int s,int far) 32 { 33 if(candy[s]<even) 34 { 35 candy[s]++; 36 return true; 37 } 38 39 for(int i=0; i<vect[s].size(); i++) 40 { 41 int t=vect[s][i]; 42 if(!edge[t].vis && edge[t].to!=far) 43 { 44 edge[t].vis=1; 45 if(DFS(edge[t].to, s)) return true; 46 edge[t].vis=0; //不成功,抹去标记 47 } 48 } 49 return false; 50 } 51 52 int cal(int n) 53 { 54 LL sum=0; 55 for(int i=1; i<=n; i++) sum+=candy[i]; 56 even=sum/n; 57 if( !cansolve(n, sum) ) 58 { 59 printf("NO\n"); 60 return 0; 61 } 62 add_node(n, 1);//建图 63 add_node(1, n); 64 for(int i=1; i<n; i++) 65 { 66 add_node(i, i+1); 67 add_node(i+1, i); 68 } 69 70 71 for(int i=1; i<=n; i++) //处理多2的 72 { 73 if(candy[i]-even==2) 74 { 75 candy[i]=even; 76 if(!DFS(i, i+1) || !DFS(i, i-1) ) 77 { 78 printf("NO\n"); 79 return 0; 80 } 81 } 82 } 83 84 for(int i=1; i<=n; i++) //处理多1的 85 { 86 if(candy[i]-even==1 ) 87 { 88 candy[i]=even; 89 if( !DFS(i, -1) ) 90 { 91 printf("NO\n"); 92 return false; 93 } 94 } 95 } 96 for(int i=1; i<=n; i++) 97 { 98 if(candy[i]!=even )//不能平均分配 99 { 100 printf("NO\n"); 101 return false; 102 } 103 } 104 return true; 105 } 106 107 vector<pii> ans; 108 109 int main() 110 { 111 freopen("input.txt", "r", stdin); 112 int t, n; 113 cin>>t; 114 while(t--) 115 { 116 scanf("%d",&n); 117 for(int i=1; i<=n; i++) vect[i].clear(); 118 119 for(int i=1; i<=n; i++) scanf("%d", &candy[i]); 120 edge_cnt=0; 121 122 if(n==1)//特判 123 { 124 printf("YES\n0\n"); 125 continue; 126 } 127 else if(n==2) 128 { 129 if(candy[1]==candy[2]) printf("YES\n0\n"); 130 else if( abs(candy[1]-candy[2])==2 ) 131 { 132 printf("YES\n1\n"); 133 if( candy[1]>candy[2]) printf("1 2\n"); 134 else printf("2 1\n"); 135 } 136 else puts("NO"); 137 continue; 138 } 139 140 141 if(cal(n)) 142 { 143 ans.clear(); 144 for(int i=0; i<edge_cnt; i+=2) 145 { 146 if( edge[i].vis && edge[i+1].vis ) continue; //抵消了 147 if( edge[i].vis ) ans.push_back( make_pair(edge[i].from, edge[i].to) ); 148 if( edge[i+1].vis ) ans.push_back( make_pair(edge[i+1].from, edge[i+1].to)); 149 } 150 printf("YES\n%d\n", ans.size()); 151 for(int i=0; i<ans.size(); i++) printf("%d %d\n", ans[i].first, ans[i].second ); 152 } 153 } 154 return 0; 155 }
WA代码
时间: 2024-10-26 08:20:31