图论总结(一)
这几天做了一些图论的题目,现总结一下。
代码:
//uva11374 #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> using namespace std; const int N=1100,M=50010; int n,m,len,num,sl,cnt,bl; int first[N],bf[N],dfn[N],low[N],sccno[N],size[N],s[N],d[N]; struct node{ int x,y,next; }a[M],b[M]; int minn(int x,int y){return x<y ? x:y;} int maxx(int x,int y){return x>y ? x:y;} void ins(int x,int y,bool bk) { if(!bk) { len++; a[len].x=x;a[len].y=y; a[len].next=first[x];first[x]=len; } else{ bl++; b[bl].x=x;b[bl].y=y; b[bl].next=bf[x];bf[x]=bl; } } void tarjan(int x,int fa) { dfn[x]=low[x]=++num; s[++sl]=x; for(int i=first[x];i;i=a[i].next) { int y=a[i].y; if(!dfn[y]) { tarjan(y,x); low[x]=minn(low[x],low[y]); } else if(!sccno[y]) low[x]=minn(low[x],dfn[y]); } if(dfn[x]==low[x]) { cnt++; int z=0; while(z!=x) { z=s[sl]; sccno[z]=cnt; size[cnt]++; sl--; } } } int dp(int x) { if(d[x]) return d[x]; d[x]=size[x]; for(int i=bf[x];i;i=b[i].next) { int y=b[i].y; d[x]=maxx(d[x],dp(y)+size[x]); } return d[x]; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); len=0;num=0;sl=0;cnt=0;bl=0; memset(bf,0,sizeof(bf)); memset(first,0,sizeof(first)); memset(dfn,0,sizeof(dfn)); memset(sccno,0,sizeof(sccno)); memset(size,0,sizeof(size)); memset(d,0,sizeof(d)); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); ins(x,y,0); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,0); for(int i=1;i<=len;i++) { int x=a[i].x; int y=a[i].y; if(sccno[x]!=sccno[y]) ins(sccno[x],sccno[y],1); } int ans=0; for(int i=1;i<=cnt;i++) ans=maxx(ans,dp(i)); printf("%d\n",ans); } return 0; }
//uva10917 #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<queue> using namespace std; const int N=1100,M=N*N; int n,m,len; int first[N],dis[N],f[N]; bool vis[N]; struct node{ int x,y,d,next; }a[M]; queue<int> q; void ins(int x,int y,int d) { len++; a[len].x=x;a[len].y=y;a[len].d=d; a[len].next=first[x];first[x]=len; } void spfa(int s) { memset(dis,63,sizeof(dis)); memset(vis,0,sizeof(vis)); while(!q.empty()) q.pop(); q.push(s);vis[s]=1;dis[s]=0; while(!q.empty()) { int x=q.front();q.pop(); vis[x]=0; for(int i=first[x];i;i=a[i].next) { int y=a[i].y; if(dis[y] > dis[x]+a[i].d) { dis[y]=dis[x]+a[i].d; if(!vis[y]) vis[y]=1,q.push(y); } } } } int dp(int x) { if(vis[x]) return f[x]; vis[x]=1; for(int i=first[x];i;i=a[i].next) if(dis[a[i].y]<dis[x]) f[x]+=dp(a[i].y); return f[x]; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); while(1) { scanf("%d",&n); if(!n) return 0; scanf("%d",&m); len=0; memset(first,0,sizeof(first)); for(int i=1;i<=m;i++) { int x,y,d; scanf("%d%d%d",&x,&y,&d); ins(x,y,d),ins(y,x,d); } spfa(2); memset(f,0,sizeof(f)); memset(vis,0,sizeof(vis)); f[2]=1;vis[2]=1; printf("%d\n",dp(1)); } return 0; }
//LA4080/uva1416 #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<queue> using namespace std; typedef long long LL; const int N=110,M=1100,INF=(int)1e9; int n,m,l,len; int first[N],dis[N],p[N]; LL ans0,ans[2*M]; bool vis[N]; struct node{ int x,y,d,next; bool bk,t; }a[2*M]; queue<int> q; LL maxx(LL x,LL y){return x>y ? x:y;} void ins(int x,int y,int d) { len++; a[len].bk=1;a[len].t=0; a[len].x=x;a[len].y=y;a[len].d=d; a[len].next=first[x];first[x]=len; } void spfa(int s,bool tmp) { while(!q.empty()) q.pop(); memset(vis,0,sizeof(vis)); memset(dis,63,sizeof(dis)); q.push(s);vis[s]=1;dis[s]=0; while(!q.empty()) { int x=q.front();vis[x]=0;q.pop(); for(int i=first[x];i!=-1;i=a[i].next) { if(!a[i].bk) continue; int y=a[i].y; if(dis[y]>dis[x]+a[i].d) { dis[y]=dis[x]+a[i].d; if(!vis[y]) vis[y]=1,q.push(y); } } } if(tmp) { for(int i=0;i<len;i++) { a[i].t=0; int x=a[i].x,y=a[i].y; if(dis[x]==dis[y]+a[i].d) a[i].t=a[i^1].t=1; } } } int get(int x) { int sum=0; for(int i=1;i<=n;i++) if(dis[i]<INF) sum+=dis[i]; else sum+=l; return sum; } void find() { for(int i=1;i<=n;i++) { spfa(i,1); int now=get(i); ans0+=now; for(int k=0;k<len;k++) { int x=a[k].x,y=a[k].y; if(a[k].t) { a[k].bk=0;a[k^1].bk=0; spfa(i,0); a[k].bk=1;a[k^1].bk=1; ans[k]+=get(i); } else ans[k]+=now; } } } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); while(scanf("%d%d%d",&n,&m,&l)!=EOF) { len=-1;ans0=0; memset(first,-1,sizeof(first)); memset(ans,0,sizeof(ans)); for(int i=1;i<=m;i++) { int x,y,d; scanf("%d%d%d",&x,&y,&d); ins(x,y,d),ins(y,x,d); } find(); LL mx=ans0; for(int i=0;i<len;i++) mx=maxx(mx,ans[i]); printf("%lld %lld\n",ans0,mx); } return 0; }
//uva10537 #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<queue> #include<cmath> using namespace std; typedef long long LL; const int N=1010,M=200010; int n,m,len,st,ed,al; int first[N],p[N],ans[N]; LL d[N]; bool vis[N]; struct node{ int x,y,next; }a[M]; queue<int> q; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=first[x];first[x]=len; } void spfa(int s) { while(!q.empty()) q.pop(); memset(vis,0,sizeof(vis)); memset(d,127,sizeof(d)); memset(p,-1,sizeof(p)); q.push(s);vis[s]=1;d[s]=n; while(!q.empty()) { int x=q.front();vis[x]=0;q.pop(); LL now=d[x]; if(x>=32) now=d[x]+1;//a~z else { now=(LL)d[x]*20/19; while(now-(LL)ceil(now/20.0)<d[x]) now++; } for(int i=first[x];i;i=a[i].next) { int y=a[i].y; if(d[y]>now) { d[y]=now; p[y]=x; if(!vis[y]) vis[y]=1,q.push(y); } if(d[y]==now && x<p[y]) p[y]=x; } } } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T=0; while(1) { scanf("%d",&m);getchar(); if(m==-1) return 0; printf("Case %d:\n",++T); len=0; memset(first,0,sizeof(first)); char x,y,c; for(int i=1;i<=m;i++) { scanf("%c%c%c",&x,&c,&y);getchar(); ins(x-'A',y-'A'); ins(y-'A',x-'A'); } scanf("%d",&n);getchar(); scanf("%c%c%c",&x,&c,&y); st=x-'A',ed=y-'A'; spfa(ed); int now=st;al=1;ans[1]=st; while(p[now]!=-1) ans[++al]=p[now],now=p[now]; printf("%lld\n",d[st]); for(int i=1;i<al;i++) printf("%c-",ans[i]+'A'); printf("%c\n",ed+'A'); } return 0; }
/* uva11090 该程序没有AC,对拍发现有些数据和答案差了0.01, 估计是精度问题(这个程序确定的范围更小,我觉得是对的) */ #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<queue> #include<cmath> using namespace std; const int N=60,M=60*60*2; double INF=(double)1e9; int n,m,len; int first[N],p[N]; double dis[N]; bool vis[N]; struct node{ int x,y,next; double d; }a[M]; queue<int> q; double maxx(double x,double y){return x>y ? x:y;} double minn(double x,double y){return x<y ? x:y;} void ins(int x,int y,double d) { len++; a[len].x=x;a[len].y=y;a[len].d=d; a[len].next=first[x];first[x]=len; } bool spfa(int s) { while(!q.empty()) q.pop(); memset(vis,0,sizeof(vis)); memset(p,0,sizeof(p)); for(int i=1;i<=n;i++) dis[i]=INF; q.push(s);vis[s]=1;dis[s]=0; while(!q.empty()) { int x=q.front();p[x]++;vis[x]=0;q.pop(); if(p[x]>=n) return 1; for(int i=first[x];i;i=a[i].next) { int y=a[i].y; if(dis[y]>(dis[x]+a[i].d)) { dis[y]=dis[x]+a[i].d; if(!vis[y]) vis[y]=1,q.push(y); } } } return 0; } bool check(double c) { for(int i=1;i<=len;i++) a[i].d-=c; bool bk=0; for(int i=1;i<=n;i++) { bk=spfa(i); if(bk==1) break; } for(int i=1;i<=len;i++) a[i].d+=c; return bk; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T; scanf("%d",&T); for(int TT=1;TT<=T;TT++) { printf("Case #%d: ",TT); scanf("%d%d",&n,&m); len=0; memset(first,0,sizeof(first)); double mx=0,mn=INF; for(int i=1;i<=m;i++) { int x,y; double d; scanf("%d%d%lf",&x,&y,&d); mx=maxx(mx,d); mn=minn(mn,d); ins(x,y,d); } double l=mn,r=mx,mid; double ans=-1; // printf("r = %lf mx = %lf\n",r,mx); if(!check(mx+1)) printf("No cycle found.\n"); else{ while(l<r && (r-l)>(1e-3)) { mid=(l+r)/2;//l+(r-l)/2; if(check(mid)) r=mid; else l=mid; } printf("%.2lf\n",l); } } return 0; }
//uva11478 #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<queue> #include<cmath> using namespace std; const int N=550,M=4000; int n,m,len,ql; int first[N],dis[N],cnt[N],sum[N],q[N]; bool vis[N]; struct node{ int x,y,d,next; }a[M]; void ins(int x,int y,int d) { len++; a[len].x;a[len].y=y;a[len].d=d; a[len].next=first[x];first[x]=len; } bool spfa(int s) { ql=0; memset(dis,63,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(cnt,0,sizeof(cnt)); q[++ql]=s;vis[s]=1;dis[s]=0; while(ql) { int x=q[ql];ql--;vis[x]=0;cnt[x]++; if(cnt[x]==n+1) return 0; for(int i=first[x];i;i=a[i].next) { int y=a[i].y; if(dis[y]>dis[x]+a[i].d) { dis[y]=dis[x]+a[i].d; if(!vis[y]) vis[y]=1,q[++ql]=y; } } } return 1; } bool check(int c) { for(int i=1;i<=len;i++) a[i].d-=c; bool bk=spfa(0); for(int i=1;i<=len;i++) a[i].d+=c; return bk; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); while(scanf("%d%d",&n,&m)!=EOF) { len=0; memset(first,0,sizeof(first)); memset(sum,0,sizeof(sum)); for(int i=1;i<=n;i++) ins(0,i,0); for(int i=1;i<=m;i++) { int x,y,d; scanf("%d%d%d",&x,&y,&d); ins(x,y,d); } if(check(10010)) printf("Infinite\n"); else { if(!check(1)) printf("No Solution\n"); else { int l=1,r=10000; while(l<r) { int mid=(l+r+1)/2; if(check(mid)) l=mid; else r=mid-1; if(l==r) break; } printf("%d\n",l); } } } return 0; }
//poj1201 #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<queue> #include<cmath> using namespace std; const int N=50100,M=4*50100; int m,len,ql,mx; int first[N],dis[N],q[N]; bool vis[N]; struct node{ int x,y,d,next; }a[M]; int maxx(int x,int y){return x>y ? x:y;} void ins(int x,int y,int d) { len++; a[len].x=x;a[len].y=y;a[len].d=d; a[len].next=first[x];first[x]=len; } int spfa(int s) { ql=0; memset(dis,-1,sizeof(dis)); memset(vis,0,sizeof(vis)); q[++ql]=s;vis[s]=1;dis[s]=0; while(ql) { int x=q[ql];ql--;vis[x]=0; for(int i=first[x];i;i=a[i].next) { int y=a[i].y; if(dis[y]<dis[x]+a[i].d) { dis[y]=dis[x]+a[i].d; if(!vis[y]) vis[y]=1,q[++ql]=y; } } } return dis[mx]; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); len=0; memset(first,0,sizeof(first)); scanf("%d",&m); mx=-1; for(int i=1;i<=m;i++) { int x,y,d; scanf("%d%d%d",&x,&y,&d); x++;y++; ins(x-1,y,d); mx=maxx(mx,y); } for(int i=0;i<=mx;i++) ins(i,i+1,0); for(int i=1;i<=mx;i++) ins(i,i-1,-1); /* 0<=dis[i]-dis[i-1]<=1 注意要建 i-->i+1 和 i-->i-1 两种辅助边 如果不建dis[i]-dis[i-1]<=1这条边就会出现一个数选了多遍的情况 */ printf("%d\n",spfa(0)); return 0; }
//poj1275 #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<queue> #include<cmath> using namespace std; const int N=30,M=1100; int n,len; int num[N],lim[N],cnt[N],dis[N],first[N]; bool vis[N]; struct node{ int x,y,d,next; }a[M]; queue<int> q; void ins(int x,int y,int d) { len++; a[len].x=x;a[len].y=y;a[len].d=d; a[len].next=first[x];first[x]=len; } bool spfa(int s,int now) { for(int i=len;i>=len-6;i--) a[i].d-=now; a[1].d+=now; bool bk=1; while(!q.empty()) q.pop(); memset(vis,0,sizeof(vis)); memset(dis,-63,sizeof(dis)); memset(cnt,0,sizeof(cnt)); q.push(s);vis[s]=1;dis[s]=0; while(!q.empty()) { int x=q.front();q.pop();vis[x]=0;cnt[x]++; if(cnt[x]>=25) {bk=0;break;} for(int i=first[x];i;i=a[i].next) { int y=a[i].y; if(dis[y]<dis[x]+a[i].d) { dis[y]=dis[x]+a[i].d; if(!vis[y]) vis[y]=1,q.push(y); } } } a[1].d-=now; for(int i=len;i>=len-6;i--) a[i].d+=now; return bk; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T; scanf("%d",&T); while(T--) { len=0; memset(first,0,sizeof(first)); memset(num,0,sizeof(num)); for(int i=1;i<=24;i++) scanf("%d",&lim[i]); scanf("%d",&n); for(int i=1;i<=n;i++) { int x; scanf("%d",&x);x++; num[x]++; } ins(0,24,0); for(int i=1;i<=24;i++) ins(i-1,i,0); for(int i=1;i<=24;i++) ins(i,i-1,-num[i]); for(int i=8;i<=24;i++) ins(i-8,i,lim[i]); for(int i=1;i<=7;i++) ins(i+16,i,lim[i]); if(!spfa(0,n)) printf("No Solution\n"); else { int l=0,r=n; while(l<r) { int mid=(l+r)>>1; if(spfa(0,mid)) r=mid; else l=mid+1; } printf("%d\n",l); } } return 0; }