zoj 3583 Simple Path

来源:互联网 发布:广州ps美工培训 编辑:程序博客网 时间:2024/06/05 06:07

题意:给定一个无向图,输出不在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;}


原创粉丝点击