首页 > 其他 > 详细

ZOJ3760 Treasure Hunting

时间:2014-03-03 21:04:37      阅读:466      评论:0      收藏:0      [点我收藏+]

最大流最小割定理的应用

添加源点(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().

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<cstdlib>
#include<cmath>
using namespace std;
const int MAXM = 2000011;
const int MAXN = 511;
long long INF = 0;
struct edge
{
int v,nxt;
long long f;
};
edge e[MAXM];
int g[MAXN];
int nume,n,p;
int x[MAXN],y[MAXN],dist[MAXN];
bool vis[MAXN];
int src,sink;
int a[MAXN],b[MAXN];
int tot1,tot2;
void init()
{
memset(g,0,sizeof(g));
nume = 1;
for (int i = 1; i <= n; i++) scanf("%d%d",&x[i],&y[i]);
}
void addedge(int u,int v,long long c)
{
e[++nume].v = v;
e[nume].f = c;
e[nume].nxt = g[u];
g[u] = nume;
e[++nume].v = u;
e[nume].f = 0;
e[nume].nxt = g[v];
g[v] = nume;
}
int gcd(int a,int b)
{
if (b == 0) return a;
return gcd(b,a%b);
}
queue<int>que;
void bfs()
{
memset(dist,0,sizeof(dist));
while (!que.empty()) que.pop();
vis[src] = 1;
que.push(src);
while (!que.empty())
{
int u = que.front();
que.pop();
for (int i = g[u];i;i = e[i].nxt)
if (e[i].f && !vis[e[i].v])
{
que.push(e[i].v);
dist[e[i].v] = dist[u] + 1;
vis[e[i].v] = 1;
}
}
}
/*inline long long mint(int x,long long y)
{
if (x < y) return x;
return y;
}*/
long long dfs(int u,long long delta)
{
if (u == sink)
{
return delta;
}
else
{
long long ret = 0;
for (int i = g[u]; delta && i; i = e[i].nxt)
if (e[i].f && dist[e[i].v] == dist[u] +1)
{
long long dd = dfs(e[i].v,min(e[i].f,delta));
e[i].f -= dd;
e[i ^ 1].f += dd;
delta -= dd;
ret += dd;
}
return ret;
}
}
long long maxflow()
{
long long ret = 0;
while (1)
{
memset(vis,0,sizeof(vis));
bfs();
if (!vis[sink]) return ret;
ret += dfs(src,INF);
}
}
int main()
{
while (scanf("%d%d",&n,&p) != EOF)
{
init();
src = 0; sink = n + 1;
tot1 = tot2 = 0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for (int i = 1; i <= n; i++)
{
int s1 = x[i] % 2,s2 = y[i] % 2;
int s = s1 + s2;
if (s % 2 == 0) a[++tot1] = i; else b[++tot2] = i;
}
long long ans = 0ll;
for (int i = 1;i <= n; i++) ans += (x[i] & y[i]);
INF = ans;
for (int i = 1; i <= tot1; i++) addedge(0,a[i],x[a[i]] & y[a[i]]);
for (int i = 1; i <= tot2; i++) addedge(b[i],n + 1,x[b[i]] & y[b[i]]);
for (int i = 1; i <= tot1; i++)
for (int j = 1; j <= tot2; j++)
if (gcd(x[a[i]] ^ y[a[i]] ^ x[b[j]] ^ y[b[j]],p) == 1) addedge(a[i],b[j],INF);
ans = ans - maxflow();
cout<<ans<<endl;
}
return 0;
}

ZOJ3760 Treasure Hunting,布布扣,bubuko.com

ZOJ3760 Treasure Hunting

原文:http://www.cnblogs.com/yuhao1994/p/3577800.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!