您的位置:首页 > 其它

zoj 3583 Simple Path

2012-10-05 10:21 218 查看
题意:给定一个无向图,输出不在s到d的简单路径上的点

题解:

1方法1dfs

先删点,然后从(前提:删除的不是s且s没有被拜访)s搜一次,再从(前提:删除的不是d且d没有被拜访)d搜一次,搜不到的点就是不再s到d简单路径上的点。

一开始错在这个图上了:

从0到4

0 1

0 2

0 3

0 4

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
bool v[111],not_in[111],a[111][111];
int n,m,s,d;
void dfs(int x)
{
for(int i=0;i<=n-1;i++)
if((!v[i])&&a[x][i])
{
v[i]=true;
dfs(i);
}
}
int main()
{
while(scanf("%d%d%d%d",&n,&m,&s,&d)!=EOF)
{
memset(a,false,sizeof(a));
memset(not_in,false,sizeof(not_in));
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
a[u][v]=true;
a[v][u]=true;
}
for(int i=0;i<=n-1;i++)
{
memset(v,false,sizeof(v));
v[i]=true;
if(!v[s])dfs(s);//必须加上!v
if(!v[d])dfs(d);//必须加上!v
/*
0 1
0 2
0 3
0 4
看这种图,必须删除点s后才能发现不在简单路径上的点。
*/
for(int j=0;j<=n-1;j++)
if(!v[j]&&j!=s&&j!=d)not_in[j]=true;
}
int ans=0;
for(int i=0;i<=n-1;i++)
if(not_in[i])ans++;
printf("%d\n",ans);
}
return 0;
}


2.建立网络流模型求解

注意本题有重边,必须处理重边否则会出现错误。

建立图的依据:u如果不在简单路径上,则有s->u的路径与d->u的路径必然会经过同一个点。

方法:

建立超级汇点ss,超级源点dd,ss到s连流量为1的边,dd到d连流量为1的边。原图中的边流量设为无穷。对于每个点拆点,之间流量为1.但是对于u这个点,流量为2。

u和超级汇点也连边。

求超级源点到超级汇点的流量。

#include<iostream>
#include<cstdio>
#include<cstring>
#define INF (1<<26)
using namespace std;
template <int MAXSIZE,int MAXQ>
class DINIC//建立对象时先调用清除函数
{
public:
void clear(int n0)
{
m=0;n=n0;
memset(edge,-1,sizeof(edge));
memset(next,-1,sizeof(next));
}

void addedge(int u,int v,int c)
{
to[m]=v;
cap[m]=c;
next[m]=edge[u];
edge[u]=m++;

to[m]=u;
cap[m]=0;
next[m]=edge[v];
edge[v]=m++;
}

bool bfs()
{
for(int i=0;i<=n;i++)
d[i]=-1;
int head=0,tail=0,x,y;
d[s]=0;q[0]=s;
while(head<=tail)
{
x=q[head];head=(head+1)%MAXQ;int i=edge[x];
while(i!=-1)
{
y=to[i];
if(cap[i] && d[y]==-1)
{
d[y]=d[x]+1;
if(y==t)return true;
tail=(tail+1)%MAXQ;q[tail]=y;
}
i=next[i];
}
}
return false;
}

int find(int x,int low=INF)
{
if(x==t)return low;
int ret,y,ans=0,i=edge[x];
while(i!=-1 && low>0)
{
y=to[i];
if(cap[i]>0 && d[y]==d[x]+1 && (ret=find(y,min(low,cap[i]))))
{
cap[i]-=ret;
cap[i^1]+=ret;
low-=ret;
ans+=ret;
}
i=next[i];
}
return ans;
}

int dinic(int s0,int t0)
{
s=s0;t=t0;
int ans=0;
while(bfs())
ans+=find(s);
return ans;
}
private:
int m,s,t,n;
int to[MAXSIZE],cap[MAXSIZE],next[MAXSIZE],edge[MAXSIZE],d[MAXSIZE],q[MAXQ];
};
DINIC<60010,600000> a;
bool g[201][201];
int main()
{
int n,m,s,d,supers,supert;
while(scanf("%d%d%d%d",&n,&m,&s,&d)!=EOF)
{
memset(g,false,sizeof(g));
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u][v]=true;
g[v][u]=true;
}
//s,t
int ans=0;
for(int i=0;i<=n-1;i++)
if(i!=s && i!=d)
{
a.clear(2*n+1);
supers=2*n;supert=2*n+1;
a.addedge(supers,s,1);
a.addedge(supers,d,1);
a.addedge(i+n,supert,2);

for(int x=0;x<=n-1;x++)
for(int y=0;y<=n-1;y++)
if(g[x][y])
a.addedge(x+n,y,INF);

for(int j=0;j<=n-1;j++)
if(j!=i)
a.addedge(j,j+n,1);
else
a.addedge(j,j+n,2);
int sum=a.dinic(supers,supert);
if(sum<=1)
ans++;
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: