您的位置:首页 > 其它

HDU 3472 HS BDC 混合图欧拉路径 最大流

2017-09-07 23:42 555 查看
暑假的时候做过混合图的欧拉回路,然后这次碰到的是欧拉路径。

欧拉回路网上都有详细的题解,不多说了。

然后这题主要是“路径”,所以有些区别。路径的话就可能存在一个起点一个终点,它们的度数一定是奇数。

所以做这题分以下几步。

1. 判断连通性。

2. 把原来的无向边默认一个方向去修改两个点的入度和出度,然后在图中加一条反向边,容量为1。

3. 找到度数为奇数的点,只可能为2个或0个。如果为2个,在这两点随意连边,修改度数,再加反向边,容量为1。

4. 通过每个点的入度和出度差判断是和源点连边还是和汇点连边。

5. 跑最大流,判断是否满流。

这题的数据应该是挺水的,我跑了15ms就过了。

网上有些题解的代码好像是不对的。

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <queue>

using namespace std;
const int MAXN = 100;
const int MAXM = 5000;
const int inf = 0x3f3f3f3f;
char s[1500];
int n,mp[MAXN][MAXN],head[MAXN];
int dis[MAXN],in[MAXN],out[MAXN],tol,pre[MAXN];
bool vis[MAXN];
struct Edge
{
int to,cap,flow,nex;
Edge(int to,int cap,int flow,int nex):to(to),cap(cap),flow(flow),nex(nex) {}
Edge() {}
}edge[MAXM];

void init()
{
memset(in,0,sizeof in);
memset(out,0,sizeof out);
memset(head,-1,sizeof head);
memset(vis,0,sizeof vis);
tol=0;
for (int i=0;i<MAXN;i++) pre[i]=i;
}

int find(int p) { return pre[p]==p?p:pre[p]=find(pre[p]); }

void join(int a,int b)
{
int u=find(a),v=find(b);
if (u!=v) pre[u]=v;
}

void addedge(int u,int v,int cap)
{
edge[tol]=Edge(v,cap,0,head[u]); head[u]=tol++;
edge[tol]=Edge(u,0,0,head[v]); head[v]=tol++;
}

int getnum(char ch)
{
return ch-'a'+1;
}

bool bfs(int s,int t)
{
memset(dis,-1,sizeof dis);
dis[s]=0;
queue<int> que;
que.push(s);
while (!que.empty())
{
int u=que.front();que.pop();
for (int i=head[u];~i;i=edge[i].nex)
{
int v=edge[i].to;
if (dis[v]==-1 && edge[i].cap>edge[i].flow)
{
dis[v]=dis[u]+1;
if (v==t) return true;
que.push(v);
}
}
}
return false;
}

int dfs(int u,int t,int cap)
{
if (u==t) return cap;
int flow=0,f;
for (int i=head[u];~i;i=edge[i].nex)
{
int v=edge[i].to;
if (dis[v] == dis[u]+1 && edge[i].cap>edge[i].flow)
{
f=dfs(v,t,min(cap-flow,edge[i].cap-edge[i].flow));
edge[i].flow += f;
edge[i^1].flow -= f;
flow += f;
if (flow == cap) break;
}
}
if (!flow) dis[u]=-1;
return flow;
}

int dicnic(int s,int t)
{
int flow=0,a;
while (bfs(s,t))
while ((a=dfs(s,t,inf))>0)
flow+=a;
return flow;
}

int main()
{
int t,tt=0,tag;
cin>>t;
while (t--)
{
init();
cin>>n;
for (int i=1;i<=n;i++)
{
scanf("%s%d",s,&tag);
int a=getnum(s[0]);
int b=getnum(s[strlen(s)-1]);
vis[a]=vis[b]=true;
out[a]++;
in[b]++;
join(a,b);
if (tag == 1)
addedge(b,a,1);
}
int cnt=0,sum=0,v1=0,v2=0;
bool flag=false;
for (int i=1;i<=26;i++)
if (vis[i])
for (int j=1;j<=26;j++)
if (vis[j] && find(i)!=find(j))
flag=true;
for (int i=1;i<=26;i++)
{
int k=in[i]-out[i];
if (k&1)
{
cnt++;
if (v1) v2=i;
else v1=i;
}
}
printf("Case %d: ",++tt);
if (cnt != 2 && cnt!=0) flag=true;
if (cnt == 2)
{
out[v1]++;
in[v2]++;
addedge(v2,v1,1);
}
if (flag)
{
printf("Poor boy!\n");
continue;
}
for (int i=1;i<=26;i++)
{
int k=in[i]-out[i];
if (!k) continue;
if (k>0) addedge(0,i,k/2) , sum+=k/2;
if (k<0) addedge(i,27,-k/2);
}
int ans=dicnic(0,27);
if (ans == sum )
printf("Well done!\n");
else
printf("Poor boy!\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: