您的位置:首页 > 其它

Codeforces Round #290 (Div. 2) E Fox And Dinner

2015-03-30 19:15 471 查看
刚看到这道题的时候就有感觉是一个图论题。。因为可以通过和为质数的两个数字之间建边来构图,但是怎么判成环一直在纠结,最后还是没纠结出来,就去看题解了ORZ

然后看到了奇偶建图。。瞬间开窍。。因为感觉质数环肯定是奇偶交替的数形成的,对于两个和为质数的数a,b 。a为偶数,b为奇数,源点为s,汇点为t,只需要建立如下边

s->a   容量为2

a->b   容量为1

b->t    容量为2

只要能够达到满流那么就说明有解,否则无解,因为要达到满流必须要满足每个奇数都和两个偶数相连,每个偶数都和两个奇数相连。

之后怎么把质数环搞出来呢,我用的是一个比较暴力的方法:

在残余网络中:

(1)对于一个偶数节点就搜一条容量为0的边(正边)到达一个奇数节点

(1)对于一个奇数节点就搜一条容量为1的边(反向边)到达一个偶数节点

重复(1),(2)直到搜到一个环

具体看代码吧。。。调试了好久好久。。写得比较挫。

#include<iostream>
#include<sstream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<math.h>
#include<map>
#include<time.h>
#include<set>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
#define inf 0x7fffffff
#define lc l,m,index<<1
#define rc m+1,r,index<<1|1
#define max_n 200005
#define mod 10000007
#define LL __int64
struct edge
{
int to,cap,rev;
};
vector<edge> G[max_n];
bool used[max_n];
int num[max_n];
int id[max_n];
int n;
void add_edge(int from,int to,int cap)
{
G[from].push_back((edge){to,cap,G[to].size()});
G[to].push_back((edge){from,0,G[from].size()-1});
}
int dfs(int v,int t,int f)
{
// printf("%d ",v);
if(v==t) return f;
used[v] = true;

for(int i=0;i<G[v].size();i++)
{
edge &e=G[v][i];
if(!used[e.to] && e.cap>0)
{
int d=dfs(e.to,t,min(f,e.cap));
if(d>0)
{
e.cap-=d;
G[e.to][e.rev].cap+=d;
return d;
}
}
}
return 0;
}
int max_flow(int s,int t)
{
int flow=0;
while(1)
{
memset(used,0,sizeof(used));
int f=dfs(s,t,inf);
// printf("\n");
// printf("f == %d\n",f);
// system("pause");
if(f==0) return flow;
flow+=f;
}

}
bool judge(int x)
{
for(int i=2;i<=(int)sqrt(x);i++)
{
if(x%i==0) return 0;
}
return 1;
}
bool judge1(bool a[])
{
for(int i=1;i<=n;i++)
{
if(!used[i])return 0;
}
return 1;
}
void Dfs(int v,vector<int> &ans)
{
ans.push_back(v);
used[v]=1;
int l;
if(num[v-1]%2==0)
l=0;
else
l=1;
for(int i=0;i<G[v].size();i++)
{
edge e=G[v][i];
if(!used[e.to] && e.cap==l && e.to!=0 && e.to!=10005)
Dfs(e.to,ans);
}
}
void solve()
{
int res=max_flow(0,10005);
if(res!=n)
{
// printf("%d\n",res);
printf("Impossible\n");
return ;
}

vector<int>ans[10005];
int index=0;

memset(used,0,sizeof(used));

while(!judge1(used))
{
for(int i=0;i<n;i++)
{
if(!used[i+1])
{
Dfs(i+1,ans[index++]);
}
}
}
printf("%d\n",index);
for(int i=0;i<index;i++)
{
printf("%d",ans[i].size());
for(int j=0;j<ans[i].size();j++)
printf(" %d",ans[i][j]);
printf("\n");
}
}
int main()
{
while(~scanf("%d",&n))
{

for(int i=0;i<n;i++)
scanf("%d",&num[i]);

memset(used,0,sizeof(used));

for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
if(judge(num[i]+num[j]))
{
int s=i+1;
int t=j+1;
if(num[i]%2==0 && num[j]%2!=0)
{

// printf("0-->%d-->%d-->10005\n",num[i],num[j]);
add_edge(s,t,1);
if(!used[s])
{
add_edge(0,s,2);
used[s]=1;
}
// printf("0-->%d\n",num[i]);
if(!used[t])
{
add_edge(t,10005,2);
used[t]=1;
}
}
else if(num[j]%2==0 && num[i]%2!=0)
{
// printf("0-->%d-->%d-->10005\n",num[j],num[i]);
add_edge(t,s,1);
if(!used[t])
{
add_edge(0,t,2);
used[t]=1;
}
if(!used[s])
{
add_edge(s,10005,2);
used[s]=1;
}
}
}
}
}
/*
for(int i=0;i<n;i++)
{
int s=num[i];
for(int j=0;j<G[s].size();j++)
printf("%d-->%d %d\n",s,G[s][j].to,G[s][j].cap);
}*/
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: