@KirinBill
2017-12-03T14:28:46.000000Z
字数 12849
阅读 2116
学习笔记
图论
目录
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 解题报告"