codeforces #290 div1 C(最大流,输出解)

2015-02-06 00:44:25

思路:神奇的网络流题...

  之前cf某题也是类似的网络流,不过是相加为奇数的情况。

  这一题要求相加为素数,其实也是同理的,素数必定为奇数嘛... 那么只要将奇数放在左列,偶数放在右列,然后加一个源点和所有左列点相连,容量为2,加一个汇点和所有右列点相连容量为2... 再考虑对每一个左列点,扫一遍所有右列点,如果相加为素数那么建边,容量为1。

  这么建图的原因:每个奇数一定相邻2个偶数,每个偶数一定相邻2个奇数,这样才有可能满足题意。每个奇数与两个偶数产生1的流量,与源点和汇点各产生2的流量。

  最后,要输出解。

  考虑:跑完最大流后,最大流的边容量都变成0了,反向边存的是最大流...

     所以我们找到每条容量为0的边,重新建图,对所有未标记的点跑一遍Dfs,Dfs过程中标记点已经遍历即可。

  注意:由于题目每个数 <= 10^4,但是有数相加的情况,所以如果是用素数表来判断的话,数组范围要开到2*10^4!!

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <vector>
  6 #include <map>
  7 #include <set>
  8 #include <stack>
  9 #include <queue>
 10 #include <string>
 11 #include <iostream>
 12 #include <algorithm>
 13 using namespace std;
 14 
 15 #define MEM(a,b) memset(a,b,sizeof(a))
 16 #define REP(i,n) for(int i=0;i<(n);++i)
 17 #define REV(i,n) for(int i=(n-1);i>=0;--i)
 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
 19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
 20 #define MP(a,b) make_pair(a,b)
 21 
 22 typedef long long ll;
 23 typedef pair<int,int> pii;
 24 const int INF = (1 << 30) - 1;
 25 const int MAXN = 210;
 26 const int MAXM = 50010;
 27 
 28 int pm[200010];
 29 
 30 void Pre(){
 31     FOR(i,2,20000) if(!pm[i]){
 32         for(int j = i + i; j <= 20000; j += i)
 33             pm[j] = 1;
 34     }
 35 }
 36 
 37 struct Max_flow{
 38     int first[MAXN],next[MAXM],ver[MAXM],cp[MAXM],ecnt;
 39     int lev[MAXN],st,ed;
 40     void Init(){
 41         MEM(first,-1);
 42         ecnt = 0;
 43     }
 44     void Add_edge(int u,int v,int c){
 45         next[ecnt] = first[u];
 46         ver[ecnt] = v,cp[ecnt] = c;
 47         first[u] = ecnt++;
 48         //opposite
 49         next[ecnt] = first[v];
 50         ver[ecnt] = u,cp[ecnt] = 0;
 51         first[v] = ecnt++;
 52     }
 53     bool Bfs(){
 54         queue<int> Q;
 55         MEM(lev,-1);
 56         Q.push(st);
 57         lev[st] = 0;
 58         while(!Q.empty()){
 59             int now = Q.front(); Q.pop();
 60             for(int i = first[now]; ~i; i = next[i]){
 61                 int v = ver[i];
 62                 if(lev[v] < 0 && cp[i] > 0){
 63                     lev[v] = lev[now] + 1;
 64                     Q.push(v);
 65                 }
 66             }
 67         }
 68         return lev[ed] != -1;
 69     }
 70     int Dfs(int p,int minf){
 71         if(p == ed) return minf;
 72         for(int i = first[p]; ~i; i = next[i]){
 73             int v = ver[i];
 74             if(lev[v] > lev[p] && cp[i] > 0){
 75                 int d = Dfs(v,min(cp[i],minf));
 76                 if(d > 0){
 77                     cp[i] -= d;
 78                     cp[i ^ 1] += d;
 79                     return d;
 80                 }
 81             }
 82          }
 83         return 0;
 84     }
 85     int Dinic(){
 86         int max_flow = 0,pl;
 87         while(Bfs()){
 88             while((pl = Dfs(st,INF)) > 0)
 89                 max_flow += pl;
 90         }
 91         return max_flow;
 92     }
 93 };
 94 
 95 int n;
 96 int val[MAXN],cnt[2];
 97 int first[MAXN],ecnt;
 98 vector< vector<int> > ans;
 99 vector<int> res;
100 int vis[MAXN];
101 
102 struct edge{
103     int v,next;
104 }e[MAXM];
105 
106 void Add_edge(int u,int v){
107     e[++ecnt].next = first[u];
108     e[ecnt].v = v;
109     first[u] = ecnt;
110 }
111 
112 void Dfs(int p){
113     vis[p] = 1;
114     res.push_back(p);
115     for(int i = first[p]; ~i; i = e[i].next){
116         int v = e[i].v;
117         if(!vis[v]) Dfs(v);
118     }
119 }
120 
121 int main(){
122     Pre();
123     Max_flow MF;  MF.Init();
124     scanf("%d",&n);
125     FOR(i,1,n){
126         scanf("%d",&val[i]);
127         int id = val[i] & 1;
128         cnt[id]++;
129         if(id) MF.Add_edge(0,i,2); //源点和奇数连边
130         else MF.Add_edge(i,n + 1,2); //汇点和偶数连边
131     }
132     if(cnt[0] != cnt[1]){
133         printf("Impossible\n");
134         return 0;
135     }
136     FOR(i,1,n) if(val[i] & 1){
137         FOR(j,1,n)
138             if((val[j] & 1) == 0 && !pm[val[i] + val[j]])
139                 MF.Add_edge(i,j,1);
140     }
141     MF.st = 0;
142     MF.ed = n + 1;
143     if(MF.Dinic() != n){
144         printf("Impossible\n");
145         return 0;
146     }
147     //Init
148     MEM(first,-1);
149     ecnt = 0;
150     FOR(i,1,n) if(val[i] & 1){
151         for(int j = MF.first[i]; ~j; j = MF.next[j]){
152             int v = MF.ver[j];
153             if(v && MF.cp[j] == 0){ //防止连回源点
154                 Add_edge(i,v);
155                 Add_edge(v,i);
156             }
157         }
158     }
159     FOR(i,1,n){
160         if(!vis[i]){
161             res.clear();
162             Dfs(i);
163             ans.push_back(res);
164         }
165     }
166     printf("%d\n",(int)ans.size());
167     REP(i,ans.size()){
168         printf("%d",(int)ans[i].size());
169         REP(j,ans[i].size()) printf(" %d",ans[i][j]);
170         puts("");
171     }
172     return 0;
173 }

 

posted @ 2015-02-06 00:53  Naturain  阅读(126)  评论(0编辑  收藏  举报