题目大意:

相邻的朋友可以给出自己手上最多一颗糖,n个朋友形成一个环,问给的方式能否最后使所有朋友都糖的数量相同

 

这里我用的是网络流来做的,这里n=100000,用sap的模板可以跑过

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <cstring>
  5 using namespace std;
  6 #define ll long long
  7 const int MAXN = 100010;
  8 const int MAXM = 400010;
  9 const int INF = 0x3f3f3f3f;
 10 struct Edge{
 11     int st , to ,  next, cap , flow;
 12 }edge[MAXM];
 13 
 14 int tol , head[MAXN] , gap[MAXN] , dep[MAXN] , cur[MAXN];
 15 
 16 void init(){
 17     tol = 0;
 18     memset(head , -1  , sizeof(head));
 19 }
 20 
 21 void add_edge(int u , int v , int w , int rw=0)
 22 {
 23     edge[tol].st = u , edge[tol].to=v , edge[tol].cap = w , edge[tol].flow=0;
 24     edge[tol].next = head[u] , head[u] = tol++;
 25 
 26     edge[tol].st = v , edge[tol].to = u , edge[tol].cap = rw , edge[tol].flow=0;
 27     edge[tol].next = head[v] , head[v] = tol++;
 28 }
 29 
 30 int Q[MAXN];
 31 
 32 void BFS(int start , int end)
 33 {
 34     memset(dep , -1 , sizeof(dep));
 35     memset(gap , 0 , sizeof(gap));
 36     gap[0] = 1;
 37     int front = 0 , rear = 0;
 38     dep[end] = 0;
 39     Q[rear++] = end;
 40     while(front != rear){
 41         int u  = Q[front++];
 42         for(int i=head[u] ; i!=-1 ; i=edge[i].next){
 43             int v = edge[i].to ;
 44             if(dep[v]!=-1) continue;
 45             Q[rear++] = v;
 46             dep[v] = dep[u] + 1;
 47             gap[dep[v]]++;
 48         }
 49     }
 50 }
 51 
 52 int S[MAXN];
 53 int sap(int start , int end , int N)
 54 {
 55     BFS(start , end);
 56     memcpy(cur , head , sizeof(head));
 57     int top=0;
 58     int u=start;
 59     int ans = 0;
 60     while(dep[start]<N)
 61     {
 62         if(u == end){
 63             int Min = INF;
 64             int inser;
 65             for(int i=0 ; i<top ; i++)
 66                 if(Min>edge[S[i]].cap-edge[S[i]].flow){
 67                     Min = edge[S[i]].cap-edge[S[i]].flow;
 68                     inser = i;
 69                 }
 70             for(int i=0 ; i<top ; i++){
 71                 edge[S[i]].flow+=Min;
 72                 edge[S[i]^1].flow-=Min;
 73             }
 74             ans+=Min;
 75             top = inser;
 76             u = edge[S[top]^1].to;
 77             continue;
 78         }
 79         bool flag = false;
 80         int v ;
 81         for(int i=cur[u] ; i!=-1 ; i=edge[i].next){
 82             v = edge[i].to;
 83             if(edge[i].cap-edge[i].flow && dep[v]+1==dep[u]){
 84                 flag = true;
 85                 cur[u] = i;
 86                 break;
 87             }
 88         }
 89         if(flag){
 90             S[top++] = cur[u];
 91             u = v;
 92             continue;
 93         }
 94         int Min = N;
 95         for(int i=head[u] ; i!=-1 ; i=edge[i].next){
 96             if(edge[i].cap-edge[i].flow && dep[edge[i].to]<Min){
 97                 Min = dep[edge[i].to];
 98                 cur[u] = i;
 99             }
100         }
101         gap[dep[u]]--;
102         if(!gap[dep[u]]) return ans;
103         dep[u] = Min+1;
104         gap[dep[u]]++;
105         if(u != start) u = edge[S[--top]^1].to;
106     }
107     return ans;
108 }
109 int n , m , val[MAXN] , id[MAXN] , in[MAXN] , out[MAXN] , x,  y , fl;
110 ll sum , ave;
111 int main()
112 {
113   // freopen("in.txt" , "r" , stdin);
114     int cas;
115     scanf("%d",&cas);
116     while(cas--){
117         init();
118         scanf("%d" , &n);
119         sum = 0;
120         for(int i=1 ; i<=n ; i++){
121             scanf("%d" , val+i);
122             sum+=val[i];
123         }
124         bool ok = true;
125         if(sum%n != 0){
126             ok = false;
127         }
128         if(!ok){
129             puts("NO");
130             continue;
131         }
132         ave = sum/n;
133         for(int i=1 ; i<=n ; i++){
134             if(abs(val[i]-ave)>2) ok = false;
135         }
136         if(!ok){
137             puts("NO");
138             continue;
139         }
140         add_edge(n , 1 , 1 , 1);
141         for(int i=2 ; i<=n ; i++){
142             add_edge(i , i-1 , 1 , 1);
143         }
144         int min_flow = 0;
145         for(int i=1 ; i<=n ; i++){
146             if(val[i]>ave){
147                 add_edge(0 , i , val[i]-ave);
148             }
149             else if(val[i]<ave){
150                 add_edge(i , n+1 , ave-val[i]);
151                 min_flow+=ave-val[i];
152             }
153         }
154         int flow = sap(0 ,n+1 , n+2);
155       //  cout<<flow<<" "<<min_flow<<endl;
156         if(flow!=min_flow) ok = false;
157         if(!ok){
158             puts("NO");
159             continue;
160         }
161         int rec[MAXN][2] , tot=0;
162         for(int i=0 ; i<tol ; i+=2){
163             if(edge[i].st>=1 && edge[i].to<=n){
164                 /*if(edge[i].flow + edge[i^1].flow == 0){
165                     cout<<edge[i].st<<" "<<edge[i].to<<endl;
166                     cout<<edge[i^1].st<<" "<<edge[i^1].to<<endl;
167                     continue;
168                 }*/
169                 if(edge[i].flow>0) rec[tot][0] = edge[i].st , rec[tot++][1] = edge[i].to;
170                 else if(edge[i^1].flow>0) rec[tot][0] = edge[i^1].st , rec[tot++][1] = edge[i^1].to;
171             }
172         }
173         printf("YES\n%d\n" , tot);
174         for(int i=0 ; i<tot ; i++) printf("%d %d\n" , rec[i][0] , rec[i][1]);
175     }
176     return 0;
177 }

 

 posted on 2015-08-11 11:00  Love风吟  阅读(219)  评论(0编辑  收藏  举报