@KirinBill
2017-12-03T06:28:46.000000Z
字数 12849
阅读 2632
学习笔记 图论
目录
void Tarjan_SCC(int u){static int idx=0;static int low[MAXN];static bool inS[MAXN];static stack<int> stk;dfn[u]=low[u]=++idx;stk.push(u);inS[u]=true;for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(!dfn[v]){Tarjan_SCC(v);low[u]=min(low[u],low[v]);}else if(inS[v]) low[u]=min(low[u],dfn[v]);}if(dfn[u]==low[u]){++tot;int now;do{now=stk.top();stk.pop();inS[now]=false;scc[now]=tot;}while(now!=u);}}//注意,图可能并不连通inline void Tarjan_SCC(){for(int i=1;i<=n;++i){if(!dfn[i]) Tarjan_SCC(i);}}
代码:
#include <cstdio>#include <stack>#include <queue>#include <algorithm>using std::stack;using std::min;using std::max;using std::queue;const int MAXN=1e4+5,MAXM=1e5+5;int n,m,tot;int he[MAXN],w[MAXN],scc[MAXN];struct line{int to,nex;}ed[MAXM];namespace preG{int he[MAXN],dfn[MAXN],w[MAXN];struct line{int to,nex;}ed[MAXM];inline void addE(int u,int v){static int cnt=0;ed[++cnt]=(line){v,he[u]};he[u]=cnt;}void Tarjan_SCC(int u){static int idx=0;static int low[MAXN];static bool inS[MAXN];static stack<int> stk;dfn[u]=low[u]=++idx;stk.push(u);inS[u]=true;for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(!dfn[v]){Tarjan_SCC(v);low[u]=min(low[u],low[v]);}else if(inS[v]) low[u]=min(low[u],dfn[v]);}if(dfn[u]==low[u]){++tot;int now;do{now=stk.top();stk.pop();inS[now]=false;scc[now]=tot;::w[tot]+=w[now];}while(now!=u);}}inline void Tarjan_SCC(){for(int i=1;i<=n;++i){if(!dfn[i]) Tarjan_SCC(i);}}}inline void addE(int u,int v){static int cnt=0;ed[++cnt]=(line){v,he[u]};he[u]=cnt;}int inD[MAXN];inline void rebuild(){using preG::he;using preG::ed;preG::Tarjan_SCC();for(int u=1;u<=n;++u){for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(scc[u]!=scc[v]){addE(scc[u],scc[v]);++inD[scc[v]];}}}}inline int DAG_DP(){static int dp[MAXN];static queue<int> que;for(int i=1;i<=tot;++i){dp[i]=w[i];if(!inD[i]) que.push(i);}int u;while(que.size()){u=que.front();que.pop();for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;dp[v]=max(dp[v],dp[u]+w[v]);if(--inD[v]==0) que.push(v);}}int ret=0;for(int i=1;i<=tot;++i)ret=max(ret,dp[i]);return ret;}int main(){using preG::addE;using preG::w;scanf("%d%d",&n,&m);for(int i=1;i<=n;++i)scanf("%d",&w[i]);for(int i=1,u,v;i<=m;++i){scanf("%d%d",&u,&v);addE(u,v);}rebuild();printf("%d",DAG_DP());return 0;}
代码:
#include <cstdio>#include <stack>#include <algorithm>using std::stack;using std::min;using std::max;const int MAXN=105;int n,tot,ans1,ans2;int he[MAXN],scc[MAXN],dfn[MAXN],inD[MAXN],outD[MAXN];struct line{int to,nex;}ed[MAXN*MAXN];inline void addE(int u,int v){static int cnt=0;ed[++cnt]=(line){v,he[u]};he[u]=cnt;}void Tarjan_SCC(int u){static int idx;static int low[MAXN];static bool inS[MAXN];static stack<int> stk;dfn[u]=low[u]=++idx;stk.push(u);inS[u]=true;for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(!dfn[v]){Tarjan_SCC(v);low[u]=min(low[u],low[v]);}else if(inS[v]) low[u]=min(low[u],dfn[v]);}if(dfn[u]==low[u]){++tot;int now;do{now=stk.top();stk.pop();inS[now]=false;scc[now]=tot;}while(now!=u);}}inline void Tarjan_SCC(){for(int i=1;i<=n;++i){if(!dfn[i]) Tarjan_SCC(i);}}inline void solve(){Tarjan_SCC();for(int u=1;u<=n;++u){for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(scc[u]!=scc[v]) ++outD[scc[u]],++inD[scc[v]];}}int in=0,out=0;for(int i=1;i<=tot;++i){if(!inD[i]) ++in;if(!outD[i]) ++out;}ans1=in;ans2=max(in,out);}int main(){scanf("%d",&n);for(int i=1,v;i<=n;++i){while(scanf("%d",&v),v)addE(i,v);}solve();if(tot==1) printf("1\n0");else printf("%d\n%d",ans1,ans2);return 0;}
代码:
#include <cstdio>#include <stack>#include <algorithm>using std::stack;using std::min;const int MAXN=10005,MAXM=50005;int n,m,tot;int he[MAXN],scc[MAXN],dfn[MAXN],sz[MAXN],outD[MAXN];struct line{int to,nex;}ed[MAXM];inline void addE(int u,int v){static int cnt=0;ed[++cnt]=(line){v,he[u]};he[u]=cnt;}void Tarjan_SCC(int u){static int idx;static int low[MAXN];static bool inS[MAXN];static stack<int> stk;dfn[u]=low[u]=++idx;stk.push(u);inS[u]=true;for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(!dfn[v]){Tarjan_SCC(v);low[u]=min(low[u],low[v]);}else if(inS[v]) low[u]=min(low[u],dfn[v]);}if(dfn[u]==low[u]){++tot;int now;do{now=stk.top();stk.pop();inS[now]=false;scc[now]=tot;++sz[tot];}while(now!=u);}}inline void Tarjan_SCC(){for(int i=1;i<=n;++i){if(!dfn[i]) Tarjan_SCC(i);}}inline int solve(){Tarjan_SCC();for(int u=1;u<=n;++u){for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(scc[u]!=scc[v]) ++outD[scc[u]];}}bool flag=false;int ret;for(int i=1;i<=tot;++i){if(!outD[i]){if(flag) return 0;else{ret=sz[i];flag=true;}}}return ret;}int main(){scanf("%d%d",&n,&m);for(int i=1,u,v;i<=m;++i){scanf("%d%d",&u,&v);addE(u,v);}printf("%d",solve());return 0;}
void Tarjan_EBC(int u,int fa){static int idx;static int low[MAXN];static bool inS[MAXN];static stack<int> stk;dfn[u]=low[u]=++idx;stk.push(u);inS[u]=true;for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(!dfn[v]){Tarjan_EBC(v,u);//边(u,v)是割桥if(low[v]>dfn[u]) cut[i]=true;else low[u]=min(low[u],low[v]);}else if(v!=fa && inS[v])low[u]=min(low[u],dfn[v]);}if(dfn[u]==low[u]){++tot;int now;do{now=stk.top();stk.pop();inS[now]=false;ebc[now]=tot;}while(now!=u);}}inline void Tarjan_EBC(){for(int i=1;i<=n;++i){if(!dfn[i]) Tarjan_EBC(i,0);}}
这方面的练习题似乎不多。。。
代码:
#include <cstdio>#include <algorithm>using std::min;const int MAXN=5005,MAXM=10005;int n,m;int he[MAXN],dfn[MAXN],low[MAXN],deg[MAXN];bool G[MAXN][MAXN];struct line{int to,nex;}ed[MAXM<<1];inline void addE(int u,int v){static int cnt=0;ed[++cnt]=(line){v,he[u]};he[u]=cnt;}void Tarjan_EBC(int u,int fa){static int idx;dfn[u]=low[u]=++idx;for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(!dfn[v]){Tarjan_EBC(v,u);low[u]=min(low[u],low[v]);}else if(v!=fa && dfn[v]<dfn[u])low[u]=min(low[u],dfn[v]);}}inline void Tarjan_EBC(){for(int i=1;i<=n;++i){if(!dfn[i]) Tarjan_EBC(i,0);}}inline int cal(){Tarjan_EBC();for(int u=1;u<=n;++u){for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(low[u]!=low[v]) ++deg[low[u]];}}int ret=0;for(int i=1;i<=n;++i){if(deg[i]==1) ++ret;}return ret+1>>1;}int main(){scanf("%d%d",&n,&m);for(int i=1,u,v;i<=m;++i){scanf("%d%d",&u,&v);G[u][v]=G[v][u]=true;}for(int i=1;i<n;++i){for(int j=i+1;j<=n;++j){if(G[i][j]) addE(i,j),addE(j,i);}}printf("%d",cal());return 0;}
vector存一下各个点双。
void Tarjan_PBC(int u,int fa){static int idx;static int low[MAXN];static stack<int> stk;dfn[u]=low[u]=++idx;int son=0;for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(!dfn[v]){++son;stk.push(i);Tarjan_PBC(v,u);low[u]=min(low[u],low[v]);if(low[v]>=dfn[u]){cut[u]=true;++tot;line *e;do{e=&ed[stk.top()];stk.pop();if(blg[e->frm]!=tot){pbc[tot].push_back(e->frm);blg[e->frm]=tot;}if(blg[e->to]!=tot){pbc[tot].push_back(e->to);blg[e->to]=tot;}}while(e->frm!=u || e->to!=v);}else low[u]=min(low[u],low[v]);}else if(v!=fa && dfn[v]<dfn[u]){stk.push(i);low[u]=min(low[u],dfn[v]);}}if(!fa && son<2) cut[u]=false;}inline void Tarjan_PBC(){for(int i=1;i<=n;++i){if(!dfn[i]) Tarjan_PBC(i,0);}}
[UVa 1364] Knights of the Round Table
代码:
#include <cstdio>#include <stack>#include <algorithm>#include <vector>#include <cstring>using std::stack;using std::min;using std::vector;const int MAXN=1005,MAXM=1e6+5;int n,m,tot,idx,cnt;int he[MAXN],blg[MAXN],dfn[MAXN],col[MAXN];bool cannt[MAXN][MAXN],oddCir[MAXN];vector<int> pbc[MAXN];struct line{int frm,to,nex;}ed[MAXN*MAXN];inline void addE(int u,int v){ed[++cnt]=(line){u,v,he[u]};he[u]=cnt;}void Tarjan_PBC(int u,int fa){static int low[MAXN];static stack<int> stk;dfn[u]=low[u]=++idx;for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(!dfn[v]){stk.push(i);Tarjan_PBC(v,u);if(low[v]>=dfn[u]){pbc[++tot].clear();line *e;do{e=&ed[stk.top()];stk.pop();if(blg[e->frm]!=tot){pbc[tot].push_back(e->frm);blg[e->frm]=tot;}if(blg[e->to]!=tot){pbc[tot].push_back(e->to);blg[e->to]=tot;}}while(e->frm!=u || e->to!=v);}else low[u]=min(low[u],low[v]);}else if(v!=fa && dfn[v]<dfn[u]){stk.push(i);low[u]=min(low[u],dfn[v]);}}}inline void Tarjan_PBC(){for(int i=1;i<=n;++i){if(!dfn[i]) Tarjan_PBC(i,0);}}bool dye(int u){for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(blg[v]!=blg[u]) continue;if(col[v]==col[u]) return false;if(col[v]==-1){col[v]=col[u]^1;if(!dye(v)) return false;}}return true;}inline void cal_oddCir(){for(int i=1;i<=tot;++i){memset(col,-1,sizeof(col));for(int j=0;j<pbc[i].size();++j)blg[pbc[i][j]]=i;col[pbc[i][0]]=0;if(!dye(pbc[i][0])){for(int j=0;j<pbc[i].size();++j)oddCir[pbc[i][j]]=true;}}}inline void clear(){cnt=tot=idx=0;memset(dfn,0,sizeof(dfn));memset(cannt,false,sizeof(cannt));memset(he,0,sizeof(he));memset(oddCir,false,sizeof(oddCir));memset(blg,0,sizeof(blg));}int main(){while(scanf("%d%d",&n,&m),n && m){clear();for(int i=1,u,v;i<=m;++i){scanf("%d%d",&u,&v);cannt[u][v]=cannt[v][u]=true;}for(int i=1;i<n;++i){for(int j=i+1;j<=n;++j){if(!cannt[i][j])addE(i,j),addE(j,i);}}Tarjan_PBC();cal_oddCir();int ans=0;for(int i=1;i<=n;++i){if(!oddCir[i]) ++ans;}printf("%d\n",ans);}return 0;}
[UVa 1108] Mining Your Own Business
代码:
#include <cstdio>#include <stack>#include <algorithm>#include <cstring>#include <vector>using std::stack;using std::min;using std::vector;const int MAXN=5e4+5;int n,idx,tot,cnt,ans1;int he[MAXN],dfn[MAXN],blg[MAXN];long long ans2;bool cut[MAXN];vector<int> pbc[MAXN];struct line{int frm,to,nex;}ed[MAXN<<1];inline void addE(int u,int v){ed[++cnt]=(line){u,v,he[u]};he[u]=cnt;}void Tarjan_PBC(int u,int fa){static int low[MAXN];static stack<int> stk;dfn[u]=low[u]=++idx;int son=0;for(int i=he[u],v;i;i=ed[i].nex){v=ed[i].to;if(!dfn[v]){++son;stk.push(i);Tarjan_PBC(v,u);if(low[v]>=dfn[u]){cut[u]=true;pbc[++tot].clear();line *e;do{e=&ed[stk.top()];stk.pop();if(blg[e->frm]!=tot){pbc[tot].push_back(e->frm);blg[e->frm]=tot;}if(blg[e->to]!=tot){pbc[tot].push_back(e->to);blg[e->to]=tot;}}while(e->frm!=u || e->to!=v);}else low[u]=min(low[u],low[v]);}else if(dfn[v]<dfn[u]){stk.push(i);low[u]=min(low[u],dfn[v]);}}if(!fa && son<2) cut[u]=false;}inline void solve(){Tarjan_PBC(1,0);if(tot==1){ans1=2;ans2=(long long)pbc[1].size()*(pbc[1].size()-1)>>1;return;}ans1=0,ans2=1;for(int i=1,cnt,lim;i<=tot;++i){cnt=0,lim=pbc[i].size();for(int j=0;j<lim;++j){if(cut[pbc[i][j]]) ++cnt;}if(cnt==1) ++ans1,ans2*=lim-cnt;}}inline void clear(){idx=cnt=tot=0;memset(dfn,0,sizeof(dfn));memset(he,0,sizeof(he));memset(blg,0,sizeof(blg));memset(cut,false,sizeof(cut));}int main(){int T=0;while(scanf("%d",&n),n){++T;clear();for(int i=1,u,v;i<=n;++i){scanf("%d%d",&u,&v);addE(u,v),addE(v,u);}solve();printf("Case %d: %d %lld\n",T,ans1,ans2);}return 0;}
[7]: "国家队清华集训2012 解题报告"