ZOJ3760 Treasure Hunting

最大流最小割定理的应用

添加源点(src)与汇点(sink)

由于P是偶数,那么对于点i与j,若gcd(x[i] ^ y[i] ^ x[j] ^ y[j],p) > 1,则可共存,可将点集分为两个集合a,b(二分图),a中点的x与y坐标同奇同偶,y中点的坐标一奇一偶,src与a中点连x[i] & y[i]的边,b中点与sink连x[i]&y[i]的边。若两点不能共存(该两点一定一个在a一个在b),连INF=max的边。求出最小割,ans=sum-maxflow().

 

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #include<stack>
  7 #include<queue>
  8 #include<map>
  9 #include<cstdlib>
 10 #include<cmath>
 11 using namespace std;
 12 const int MAXM = 2000011;
 13 const int MAXN = 511;
 14 long long INF = 0;
 15 struct edge
 16 {
 17     int v,nxt;
 18     long long f;
 19 };
 20 edge e[MAXM];
 21 int g[MAXN];
 22 int nume,n,p;
 23 int x[MAXN],y[MAXN],dist[MAXN];
 24 bool vis[MAXN];
 25 int src,sink;
 26 int a[MAXN],b[MAXN];
 27 int tot1,tot2;
 28 void init()
 29 {
 30     memset(g,0,sizeof(g));
 31     nume = 1;
 32     for (int i = 1; i <= n; i++) scanf("%d%d",&x[i],&y[i]);
 33 }
 34 void addedge(int u,int v,long long c)
 35 {
 36     e[++nume].v = v;
 37     e[nume].f = c;
 38     e[nume].nxt = g[u];
 39     g[u] = nume;
 40     e[++nume].v = u;
 41     e[nume].f = 0;
 42     e[nume].nxt = g[v];
 43     g[v] = nume;
 44 }
 45 int gcd(int a,int b)
 46 {
 47     if (b == 0) return a;
 48     return gcd(b,a%b);
 49 }
 50 queue<int>que;
 51 void bfs()
 52 {
 53     memset(dist,0,sizeof(dist));
 54     while (!que.empty()) que.pop();
 55     vis[src] = 1;
 56     que.push(src);
 57     while (!que.empty())
 58     {
 59         int u = que.front();
 60         que.pop();
 61         for (int i = g[u];i;i = e[i].nxt)
 62             if (e[i].f && !vis[e[i].v])
 63         {
 64             que.push(e[i].v);
 65             dist[e[i].v] = dist[u] + 1;
 66             vis[e[i].v] = 1;
 67         }
 68     }
 69 }
 70 /*inline long long mint(int x,long long y)
 71 {
 72     if (x < y) return x;
 73     return y;
 74 }*/
 75 long long dfs(int u,long long delta)
 76 {
 77     if (u == sink)
 78     {
 79         return delta;
 80     }
 81     else
 82     {
 83         long long ret = 0;
 84         for (int i = g[u]; delta && i; i = e[i].nxt)
 85               if (e[i].f && dist[e[i].v] == dist[u] +1)
 86         {
 87             long long dd = dfs(e[i].v,min(e[i].f,delta));
 88             e[i].f -= dd;
 89             e[i ^ 1].f += dd;
 90             delta -= dd;
 91             ret += dd;
 92         }
 93         return ret;
 94     }
 95 }
 96 long long maxflow()
 97 {
 98     long long ret = 0;
 99     while (1)
100     {
101         memset(vis,0,sizeof(vis));
102         bfs();
103         if (!vis[sink]) return ret;
104         ret += dfs(src,INF);
105     }
106 }
107 int main()
108 {
109     while (scanf("%d%d",&n,&p) != EOF)
110     {
111         init();
112         src = 0; sink = n + 1;
113         tot1 = tot2 = 0;
114         memset(a,0,sizeof(a));
115         memset(b,0,sizeof(b));
116         for (int i = 1; i <= n; i++)
117         {
118             int s1 = x[i] % 2,s2 = y[i] % 2;
119             int s = s1 + s2;
120             if (s % 2 == 0) a[++tot1] = i; else b[++tot2] = i;
121         }
122         long long ans = 0ll;
123         for (int i = 1;i <= n; i++) ans += (x[i] & y[i]);
124         INF = ans;
125         for (int i = 1; i <= tot1; i++) addedge(0,a[i],x[a[i]] & y[a[i]]);
126         for (int i = 1; i <= tot2; i++) addedge(b[i],n + 1,x[b[i]] & y[b[i]]);
127         for (int i = 1; i <= tot1; i++)
128             for (int j = 1; j <= tot2; j++)
129               if (gcd(x[a[i]] ^ y[a[i]] ^ x[b[j]] ^ y[b[j]],p) == 1) addedge(a[i],b[j],INF);
130         ans = ans - maxflow();
131         cout<<ans<<endl;
132     }
133     return 0;
134 }
View Code

 

转载于:https://www.cnblogs.com/yuhao1994/p/3577800.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值