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
2.建立网络流模型求解
注意本题有重边,必须处理重边否则会出现错误。
建立图的依据:u如果不在简单路径上,则有s->u的路径与d->u的路径必然会经过同一个点。
方法:
建立超级汇点ss,超级源点dd,ss到s连流量为1的边,dd到d连流量为1的边。原图中的边流量设为无穷。对于每个点拆点,之间流量为1.但是对于u这个点,流量为2。
u和超级汇点也连边。
求超级源点到超级汇点的流量。
题解:
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; }
相关文章推荐
- zoj 3583 simple path
- ZOJ 3583 Simple Path[并查集]
- zoj 3583
- 【dfs找不在简单路径的点】ZOJ 10th Anniversary Contest C ZOJ 3583
- zoj 3583
- zoj 1610
- ZOJ 1108 FatMouse's Speed (HDU 1160) DP
- ZOJ 1409 Communication System
- ZOJ - 3780 Paint the Grid Againdfs 逆推
- ZOJ_3501 Roman Order
- zoj 1525 Air Raid 有向无环图的最小路径覆盖(匹配)
- zoj 3041 City Selection
- 【CQBZOJ 2445】[线段树][树套树]跳跃
- zoj 3175 Number of Containers
- TOJ 3365 ZOJ 3232 It's not Floyd Algorithm / 强连通分量
- ZOJ 2476 Total Amount (字符串处理)
- ZOJ 2849【瞎暴力的搜索】
- ZOJ 1457Prime Ring Problem
- POJ 2363 Blocks (ZOJ 1910) 数学
- ZOJ 2105 Number Sequence(矩阵快速幂)