zoukankan      html  css  js  c++  java
  • sss

    <更新提示>

    <第一次更新>这是一篇记录图论模板的博客


    <正文>

    最短路篇

    Dijkstra

    #include<bits/stdc++.h>
    using namespace std;
    const int N=500000,M=1000000;
    struct node
    {
    	int index,val;
    	bool operator <(const node temp)const
    	{
    		return this->val<temp.val;
    	}
    	bool operator >(const node temp)const
    	{
    		return this->val>temp.val;
    	}
    };
    struct edge
    {
    	int ver,val,next;
    }e[M*2];
    int n,m,dis[N],vis[N],Last[M*2],t,begin;
    inline void insert(int x,int y,int v)
    {
    	e[++t].ver=y;e[t].val=v;e[t].next=Last[x];Last[x]=t;
    }
    inline void dijkstra(void)
    {
    	memset(vis,0x00,sizeof vis);
    	memset(dis,0x3f,sizeof dis);
    	priority_queue< node,vector< node >,greater< node > > Heap;
    	Heap.push((node){begin,0});
    	dis[begin]=0;
    	while(!Heap.empty())
    	{
    		int temp=Heap.top().index;
    		Heap.pop();
    		if(vis[temp])continue;
    		vis[temp]=true;
    		for(int i=Last[temp];i;i=e[i].next)
    		{
    			int ver=e[i].ver;
    			if(dis[ver]>dis[temp]+e[i].val)
    			{
    				dis[ver]=dis[temp]+e[i].val;
    				Heap.push((node){ver,dis[ver]});
    			}
    		}
    	}
    }
    int main(void)
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y,v;
    		scanf("%d%d%d",&x,&y,&v);
    		insert(x,y,v);
    		insert(y,x,v);
    	}
    	scanf("%d",&begin);
    	dijkstra();
    	for(int i=1;i<=n;i++)
    		printf("The distence from %d to %d is %d
    ",begin,i,dis[i]);
    	return 0;
    }
    

    SPFA

    #include<bits/stdc++.h>
    using namespace std;
    const int N=500000,M=1000000;
    struct edge
    {
    	int ver,val,next;
    }e[M*2];
    int n,m,dis[N],vis[N],Last[M*2],t,begin;
    inline void insert(int x,int y,int v)
    {
    	e[++t].ver=y;e[t].val=v;e[t].next=Last[x];Last[x]=t;
    }
    inline void spfa(void)
    {
    	memset(vis,0x00,sizeof vis);
    	memset(dis,0x3f,sizeof dis);
    	queue < int > q;
    	dis[begin]=0;vis[begin]=true;
    	q.push(begin);
    	while(!q.empty())
    	{
    		int temp=q.front();
    		q.pop();
    		vis[temp]=false;
    		for(int i=Last[temp];i;i=e[i].next)
    		{
    			int ver=e[i].ver;
    			if(dis[ver]>dis[temp]+e[i].val)
    			{
    				dis[ver]=dis[temp]+e[i].val;
    				if(!vis[ver])
    				{
    					q.push(ver);
    					vis[ver]=true;
    				}
    			}
    		}
    	}
    }
    int main(void)
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y,v;
    		scanf("%d%d%d",&x,&y,&v);
    		insert(x,y,v);
    		insert(y,x,v);
    	}
    	scanf("%d",&begin);
    	spfa();
    	for(int i=1;i<=n;i++)
    		printf("The distence from %d to %d is %d
    ",begin,i,dis[i]);
    	return 0;
    }
    

    最小生成树篇

    Prim

    #include<bits/stdc++.h>
    using namespace std;
    const int N=500000,M=1000000;
    struct node
    {
    	int index,val;
    	bool operator <(const node temp)const
    	{
    		return this->val<temp.val;
    	}
    	bool operator >(const node temp)const
    	{
    		return this->val>temp.val;
    	}
    };
    struct edge
    {
    	int ver,val,next;
    }e[M*2];
    int n,m,dis[N],vis[N],Last[M*2],t,ans;
    inline void insert(int x,int y,int v)
    {
    	e[++t].ver=y;e[t].val=v;e[t].next=Last[x];Last[x]=t;
    }
    inline void prim(void)
    {
    	memset(vis,0x00,sizeof vis);
    	memset(dis,0x3f,sizeof dis);
    	priority_queue< node,vector< node >,greater< node > > Heap;
    	Heap.push((node){1,0});
    	dis[1]=0;
    	while(!Heap.empty())
    	{
    		node temp=Heap.top();
    		Heap.pop();
    		if(vis[temp.index])continue;
    		vis[temp.index]=true;
    		ans+=temp.val;
    		int T=temp.index;
    		for(int i=Last[T];i;i=e[i].next)
    		{
    			int ver=e[i].ver;
    			if(dis[ver]>e[i].val)
    			{
    				dis[ver]=e[i].val;
    				Heap.push((node){ver,dis[ver]});
    			}
    		}
    	}
    }
    int main(void)
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y,v;
    		scanf("%d%d%d",&x,&y,&v);
    		insert(x,y,v);
    		insert(y,x,v);
    	}
    	prim();
    	printf("%d
    ",ans);
    	return 0;
    }
    

    Kruscal

    #include<bits/stdc++.h>
    using namespace std;
    const int N=500000,M=1000000;
    struct Link{int x,y,val;}e[M];
    int n,m,ans,f[N];
    inline bool cmp(Link p1,Link p2){return p1.val<p2.val;}
    inline int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
    inline void kruscal(void)
    {
    	int cnt=0;
    	for(int i=1;i<=n;i++)
    		f[i]=i;
    	sort(e+1,e+m+1,cmp);
    	for(int i=1;i<=m;i++)
    	{
    		int x=find(e[i].x),y=find(e[i].y);
    		if(x==y)continue;
    		f[x]=y;
    		ans+=e[i].val;
    		if(++cnt==n-1)break;
    	}
    }
    int main(void)
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].val);
    	kruscal();
    	printf("%d
    ",ans);
    	return 0;
    }
    

    树上问题篇

    LCA

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define mset(name,val) memset(name,val,sizeof name)
    using namespace std;
    const int N=30000+20,MaxlogN=30;
    int n,Last[N],t,askx,asky,depth[N],f[N][MaxlogN],root=0,vis[N];
    struct edge{int ver,next;}e[N];
    inline void insert(int x,int y)
    {
    	e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
    }
    inline void input(void)
    {
    	scanf("%d",&n);
    	for(int i=1;i<n;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		insert(x,y);
    		vis[y]=1;
    	}
    	scanf("%d%d",&askx,&asky);
    	for(int i=1;i<=n;i++)
    	{
    		if(!vis[i])
    		{
    			root=i;
    			break;
    		}
    	}
    }
    inline void init(int x,int dep)
    {
    	depth[x]=dep;
    	for(int i=Last[x];i;i=e[i].next)
    	{
    		int y=e[i].ver;
    		if(f[x][0]==y)continue;
    		f[y][0]=x;
    		init(y,dep+1);
    	}
    }
    inline void dp(void)
    {
    	f[root][0]=-1;
    	for(int k=1;(1<<k)<n;k++)
    	{
    		for(int i=1;i<=n;i++)
    		{
    			if(f[i][k-1]<0)f[i][k]=-1;
    			else f[i][k]=f[f[i][k-1]][k-1];
    		}
    	}
    }
    inline int LCA(int x,int y)
    {
    	if(depth[x]>depth[y])x^=y^=x^=y;
    	for(int d=depth[y]-depth[x],i=0;d;d>>=1,i++)
    		if(d&1)y=f[y][i];
    	if(x==y)return x;
    	for(int i=MaxlogN-1;i>=0;i--)
    	{
    		if(f[x][i]!=f[y][i])
    		{
    			x=f[x][i];
    			y=f[y][i];
    		}
    	}
    	return f[x][0];
    }
    inline void reset(void)
    {
    	mset(Last,0);
    	mset(e,0);
    	mset(depth,0);
    	mset(f,0);
    	mset(vis,0);
    	t=0;
    } 
    signed main(void)
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		reset();
    		input();
    		init(root,0);
    		dp();
    		printf("%d
    ",LCA(askx,asky));
    	}
    	return 0;
    }
    

    树的直径BFS

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<vector>
    #include<cstring>
    #define mset(name,val) memset(name,val,sizeof name)
    using namespace std;
    const int N=40000+50;
    int n,m,ans,vis[N],dis[N];
    struct edge{int val,ver;};
    vector < edge > Link[N];
    inline void input(void)
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y,v;
    		scanf("%d%d%d",&x,&y,&v);
    		Link[x].push_back((edge){v,y});
    		Link[y].push_back((edge){v,x});
    	}
    }
    inline int Search(int start)
    {
    	queue< int >q;
    	mset(vis,0x00);
    	mset(dis,0x00);
    	vis[start]=1;
    	q.push(start);
    	while(!q.empty())
    	{
    		int temp=q.front();q.pop();
    		for(int i=0;i<Link[temp].size();i++)
    		{
    			if(!vis[Link[temp][i].ver])
    			{
    				vis[Link[temp][i].ver]=true;
    				dis[Link[temp][i].ver]=dis[temp]+Link[temp][i].val;
    				q.push(Link[temp][i].ver);
    			}
    		}
    	}
    	int res=0,Maxdis=0;
    	for(int i=1;i<=n;i++)
    	{
    		if(dis[i]>Maxdis)
    		{
    			Maxdis=dis[i];
    			res=i;
    		}
    	}
    	return res;
    }
    int main(void)
    {
    	input();
    	int p=Search(1);
    	printf("%d
    ",dis[Search(p)]);
    	return 0;
    }
    

    树的直径DP

    #include<cstdio>
    #include<iostream>
    #include<vector>
    #include<cstring>
    #define mset(name,val) memset(name,val,sizeof name)
    using namespace std;
    const int N=40000+50;
    int n,m,ans,vis[N],d[N],f[N];
    struct edge{int val,ver;};
    vector < edge > Link[N];
    inline void input(void)
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y,v;
    		scanf("%d%d%d",&x,&y,&v);
    		Link[x].push_back((edge){v,y});
    		Link[y].push_back((edge){v,x});
    	}
    }
    inline int dp(int x)
    {
    	vis[x]=true;
    	for(int i=0;i<Link[x].size();i++)
    	{
    		int y=Link[x][i].ver;
    		if(!vis[y])
    		{
    			dp(y);
    			f[x]=max(f[x],d[x]+d[y]+Link[x][i].val);
    			d[x]=max(d[x],d[y]+Link[x][i].val);
    		}	
    	}
    	ans=max(ans,f[x]);
    }
    int main(void)
    {
    	input();
    	dp(1);
    	printf("%d
    ",ans);
    	return 0;
    }
    

    树的重心

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<vector>
    #include<cstring>
    #define mset(name,val) memset(name,val,sizeof name)
    using namespace std;
    const int N=20000+50;
    int n,size[N],Max[N],ans,cnt;
    vector < int > Link[N];
    inline void input(void)
    {
    	scanf("%d",&n);
    	for(int i=1;i<n;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		Link[x].push_back(y);
    		Link[y].push_back(x);
    	}
    }
    inline void dp(int r,int f)
    {
    	size[r]=1;
    	for(int i=0;i<Link[r].size();i++)
    	{
    		int Son=Link[r][i];
    		if(Son==f)continue;
    		dp(Son,r);
    		size[r]+=size[Son];
    		Max[r]=max(Max[r],size[Son]);
    	}
    	Max[r]=max(Max[r],n-size[r]);
    	if(Max[r]==Max[ans]&&r<ans)ans=r;
    	if(Max[r]<Max[ans])ans=r;
    }
    int main(void)
    {		
    	Max[0]=0x3f3f3f3f;
    	input();
    	dp(1,0);
    	printf("%d
    ",ans);
    }
    

    树上差分(点)

    #include<cstdio>
    #include<cstring> 
    #include<iostream>
    using namespace std;
    const int N=100000+200,K=200000+200,MaxlogN=30;
    int n,k,cnt[N],depth[N],Last[N*2],t,f[N][MaxlogN],ans=0;
    struct edge{int ver,next;}e[N*2];
    inline void insert(int x,int y)
    {
    	e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
    }
    inline void input(void)
    {
    	scanf("%d%d",&n,&k);
    	for(int i=1;i<n;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		insert(x,y);
    		insert(y,x);
    	}
    }
    inline void init(int x,int dep)
    {
    	depth[x]=dep;
    	for(int i=Last[x];i;i=e[i].next)
    	{
    		int y=e[i].ver;
    		if(f[x][0]==y)continue;
    		f[y][0]=x;
    		init(y,dep+1);
    	}
    }
    inline void dp(void)
    {
    	f[1][0]=-1;
    	for(int k=1;(1<<k)<n;k++)
    	{
    		for(int i=1;i<=n;i++)
    		{
    			if(f[i][k-1]<0)f[i][k]=-1;
    			else f[i][k]=f[f[i][k-1]][k-1];
    		}
    	}
    }
    inline int LCA(int x,int y)
    {
    	if(depth[x]>depth[y])
    		x^=y^=x^=y;
    	for(int d=depth[y]-depth[x],i=0;d;d>>=1,i++)
    		if(1&d)y=f[y][i];
    	if(x==y)return x;
    	for(int i=MaxlogN-1;i>=0;i--)
    	{
    		if(f[x][i]!=f[y][i])
    		{
    			x=f[x][i];
    			y=f[y][i];
    		}
    	}
    	return f[x][0];
    }
    inline void Mark(void)
    {
    	for(int i=1;i<=k;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		cnt[x]++;cnt[y]++;
    		int lca=LCA(x,y);
    		cnt[lca]--;
    		if(lca!=1)cnt[f[lca][0]]--;
    	}
    }
    inline void Get_sum(int r)
    {
    	for(int i=Last[r];i;i=e[i].next)
    	{
    		int Son=e[i].ver;
    		if(Son==f[r][0])continue;
    		Get_sum(Son);
    		cnt[r]+=cnt[Son];
    	}
    	ans=max(ans,cnt[r]);
    }
    signed main(void)
    {		
    	input();
    	init(1,0);
    	dp();
    	Mark();
    	Get_sum(1);
    	printf("%d
    ",ans);
    	return 0;
    }
    

    树上差分(边)

    #include<cstdio>
    #include<cstring> 
    #include<iostream>
    using namespace std;
    const int N=100000+200,K=200000+200,MaxlogN=30;
    int n,k,cnt[N],depth[N],Last[N*2],t,f[N][MaxlogN],ans=0;
    struct edge{int ver,next;}e[N*2];
    inline void insert(int x,int y)
    {
    	e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
    }
    inline void input(void)
    {
    	scanf("%d%d",&n,&k);
    	for(int i=1;i<n;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		insert(x,y);
    		insert(y,x);
    	}
    }
    inline void init(int x,int dep)
    {
    	depth[x]=dep;
    	for(int i=Last[x];i;i=e[i].next)
    	{
    		int y=e[i].ver;
    		if(f[x][0]==y)continue;
    		f[y][0]=x;
    		init(y,dep+1);
    	}
    }
    inline void dp(void)
    {
    	f[1][0]=-1;
    	for(int k=1;(1<<k)<n;k++)
    	{
    		for(int i=1;i<=n;i++)
    		{
    			if(f[i][k-1]<0)f[i][k]=-1;
    			else f[i][k]=f[f[i][k-1]][k-1];
    		}
    	}
    }
    inline int LCA(int x,int y)
    {
    	if(depth[x]>depth[y])
    		x^=y^=x^=y;
    	for(int d=depth[y]-depth[x],i=0;d;d>>=1,i++)
    		if(1&d)y=f[y][i];
    	if(x==y)return x;
    	for(int i=MaxlogN-1;i>=0;i--)
    	{
    		if(f[x][i]!=f[y][i])
    		{
    			x=f[x][i];
    			y=f[y][i];
    		}
    	}
    	return f[x][0];
    }
    inline void Mark(void)
    {
    	for(int i=1;i<=k;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		cnt[x]++;cnt[y]++;
    		int lca=LCA(x,y);
    		cnt[lca]-=2;
    	}
    }
    inline void Get_sum(int r)
    {
    	for(int i=Last[r];i;i=e[i].next)
    	{
    		int Son=e[i].ver;
    		if(Son==f[r][0])continue;
    		Get_sum(Son);
    		cnt[r]+=cnt[Son];
    	}
    	ans=max(ans,cnt[r]);
    }
    signed main(void)
    {		
    	input();
    	init(1,0);
    	dp();
    	Mark();
    	Get_sum(1);
    	printf("%d
    ",ans);
    	return 0;
    }
    

    图的连通性篇

    Tarjan割点

    #include<bits/stdc++.h>
    using namespace std;
    const int N=90000,M=150000;
    int n,Last[M],t,cutvertex[N],dfn[N],low[N],cnt,m,ans[N],tot;
    struct edge{int ver,next;}e[M];
    inline void insert(int x,int y)
    {
    	e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
    }
    inline void input(void)
    {
    	scanf("%d%d",&n,&m);
    	int x,y;
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d",&x,&y);
    		if(x^y)insert(x,y),insert(y,x);
    	}
    }
    inline void Tarjan(int x,int root)
    {
    	dfn[x]=low[x]=++cnt;
    	int flag=0;
    	for(int i=Last[x];i;i=e[i].next)
    	{
    		int y=e[i].ver;
    		if(!dfn[y])
    		{
    			Tarjan(y,root);
    			low[x]=min(low[x],low[y]);
    			if(low[y]>=dfn[x])
    			{
    				flag++;
    				if(x!=root||flag>1)cutvertex[x]=true;
    			}
    		}
    		else low[x]=min(low[x],dfn[y]);
    	}
    }
    int main(void)
    {
    	input();
    	for(int i=1;i<=n;i++)
    		if(!dfn[i])Tarjan(i,i);
    	for(int i=1;i<=n;i++)
    	{
    		if(cutvertex[i])
    			ans[++tot]=i;
    	}
    	if(tot)printf("%d
    ",tot);
    	else printf("0
    ");
    	for(int i=1;i<=tot;i++)
    		printf("%d
    ",ans[i]);		
    }
    

    Tarjan割边

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100000+200,M=300000+200;
    int n,m,t=1,Last[M*2],dfn[N],low[N],bridge[N],cnt,tot;
    struct edge{int ver,next;}e[M*2];
    pair < int,int > ans[N];
    inline void insert(int x,int y)
    {
    	e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
    }
    inline void input(void)
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		insert(x,y);
    		insert(y,x);
    	}
    }
    inline void Tarjan(int x,int inedge)
    {
    	dfn[x]=low[x]=++cnt;
    	for(int i=Last[x];i;i=e[i].next)
    	{
    		int y=e[i].ver;
    		if(!dfn[y])
    		{
    			Tarjan(y,i);
    			low[x]=min(low[x],low[y]);
    			if(low[y]>dfn[x])
    				bridge[i]=bridge[i^1]=true;
    		}
    		else if(i!=(inedge^1))
    			low[x]=min(low[x],dfn[y]);
    	}
    }
    int main(void)
    {
    	input();
    	for(int i=1;i<=n;i++)
    		if(!dfn[i])Tarjan(i,0);
    	for(int i=2;i<t;i+=2)
    		if(bridge[i])
    		{
    			if(e[i].ver>e[i^1].ver)swap(e[i].ver,e[i^1].ver);
    			ans[++tot]=make_pair(e[i].ver,e[i^1].ver);
    		}
    	sort(ans+1,ans+tot+1);
    	for(int i=1;i<=tot;i++)
    		printf("%d %d
    ",ans[i].first,ans[i].second);
    	return 0;
    }
    

    Tarjan强连通分量

    #include<bits/stdc++.h>
    using namespace std;
    const int N=20000+200,M=80000+200;
    int n,m,dfn[N],low[N],cnt,Last[M*2],t,inSta[N],size[N],tot;
    stack < int > Stack;
    struct edge{int ver,next;}e[M*2];
    struct connected
    {
    	int len=0;
    	vector < int > List;
    }con[N];
    inline bool cmp(connected p1,connected p2)
    {
    	return p1.len>p2.len;
    }
    inline void insert(int x,int y)
    {
    	e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
    }
    inline void input(void)
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int a,b,t;
    		scanf("%d%d%d",&a,&b,&t);
    		if(t==1)insert(a,b);
    		else insert(a,b),insert(b,a);
    	}
    }
    inline void Tarjan(int x)
    {
    	dfn[x]=low[x]=++cnt;
    	Stack.push(x);inSta[x]=true;
    	for(int i=Last[x];i;i=e[i].next)
    	{
    		int y=e[i].ver;
    		if(!dfn[y])
    		{
    			Tarjan(y);
    			low[x]=min(low[x],low[y]);
    		}
    		else if(inSta[y])low[x]=min(low[x],dfn[y]);
    	}
    	if(low[x]==dfn[x])
    	{
    		int top=0;tot++;
    		while(top!=x)
    		{
    			top=Stack.top();
    			Stack.pop();
    			con[tot].len++;
    			con[tot].List.push_back(top);
    			inSta[top]=false;
    		}
    	}
    }
    inline void print(void)
    {
    	sort(con[1].List.begin(),con[1].List.end());
    	int T=1,best=1,l=con[1].len;
    	for(int i=2;i<=tot;i++)
    	{
    		if(con[i].len==con[i-1].len)
    		{
    			sort(con[i].List.begin(),con[i].List.end());
    			T++;
    		}
    		else break;
    	}
    	for(int i=2;i<=T;i++)
    	{
    		for(int j=0;j<l;j++)
    		{
    			if(con[i].List[j]<con[best].List[j])
    			{
    				best=i;
    				break;
    			}
    			else if(con[i].List[j]>con[best].List[j])
    				break;
    		}
    	}
    	for(int i=0;i<l-1;i++)
    		printf("%d ",con[best].List[i]);
    	printf("%d
    ",con[best].List[l-1]);
    }
    int main(void)
    {
    	input();
    	for(int i=1;i<=n;i++)
    		if(!dfn[i])Tarjan(i);
    	sort(con+1,con+tot+1,cmp);
    	printf("%d
    ",con[1].len);
    	print();
    	return 0;
    }
    

    Tarjan点双连通分量

    #include<bits/stdc++.h>
    using namespace std;
    const int M=500*3,N=1000;
    int m,n,Last[N],t,dfn[N],low[N],cnt,T;
    long long ans1,ans2=1;
    struct edge{int ver,next;}e[M];
    vector < int >con[N];
    stack < int > Stack;
    inline void insert(int x,int y)
    {
    	e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
    }
    inline bool input(void)
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		insert(x,y);
    		insert(y,x);
    	}
    	return true;
    }
    inline void Tarjan(int x,int root)
    {
    	dfn[x]=low[x]=++cnt;
    	Stack.push(x);
    	if(x==root&&!Last[x])
    	{
    		Stack.pop();T++;
    		con[T].push_back(x);
    		return;
    	}
    	for(int i=Last[x];i;i=e[i].next)
    	{
    		int y=e[i].ver;
    		if(!dfn[y])
    		{
    			Tarjan(y,root);
    			low[x]=min(low[x],low[y]);
    			if(low[y]>=dfn[x])
    			{
    				int top=0;T++;
    				while(top!=y)
    				{
    					top=Stack.top();
    					Stack.pop();
    					con[T].push_back(top);
    				}
    				con[T].push_back(x);
    			}
    		}
    		else low[x]=min(low[x],dfn[y]);
    	}
    }
    int main(void)
    {
    	input();
    	Tarjan(1,1);
    	for(int i=1;i<=T;i++)
    	{
    		printf("The vertex biconnected component #%d :",i);
    		for(int j=0;j<con[i].size();j++)
    			printf("%d ",con[i][j]);
    		puts("");
    	}
    	return 0;
    }
    

    Tarjan边双连通分量

    #include<bits/stdc++.h>
    using namespace std;
    const int N=10000,M=40000;
    int n,m,Last[M],dfn[N],low[N],cnt,con[N],t=1,tot;
    struct edge{int ver,next,flag;}e[M];
    inline void insert(int x,int y)
    {
    	e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
    }
    inline void input(void)
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		insert(x,y);
    		insert(y,x);
    	}
    }
    inline void Tarjan(int x,int inedge)
    {
    	dfn[x]=low[x]=++cnt;
    	for(int i=Last[x];i;i=e[i].next)
    	{
    		int y=e[i].ver;
    		if(!dfn[y])
    		{
    			Tarjan(y,i);
    			low[x]=min(low[x],low[y]);
    			if(low[y]>dfn[x])e[i].flag=e[i^1].flag=true;
    		}
    		else if(i!=(inedge^1))low[x]=min(low[x],dfn[y]);
    	}
    }
    inline void dfs(int x)
    {
    	con[x]=tot;
    	printf("%d ",x);
    	for(int i=Last[x];i;i=e[i].next)
    	{
    		if(e[i].flag)continue;
    		int y=e[i].ver;
    		if(!con[y])dfs(y);
    	}
    }
    inline void colored(void)
    {
    	for(int i=1;i<=n;i++)
    		if(!con[i])
    		{
    			++tot;
    			printf("The Edge biconnected component #%d :",tot);
    			dfs(i);
    			puts("");
    		}
    }
    int main()
    {
    	input();
    	Tarjan(1,0);
    	colored(); 
    	return 0;
    }
    

    判环篇

    Topsort

    #include<bits/stdc++.h>
    using namespace std;
    const int N=500000,M=1000000;
    struct edge
    {
    	int ver,next;
    }e[M*2];
    int n,m,Last[M*2],t,loop,indeg[N],cnt,ans[N];
    queue < int > q;
    inline void insert(int x,int y)
    {
    	e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
    }
    inline bool topsort(void)
    {
    	for(int i=1;i<=n;i++)
    		if(!indeg[i])q.push(i);
    	while(!q.empty())
    	{
    		int temp=q.front();q.pop();ans[++cnt]=temp;
    		for(int i=Last[temp];i;i=e[i].next)
    		{
    			int ver=e[i].ver;
    			indeg[ver]--;
    			if(!indeg[ver])q.push(ver);
    		}
    	}
    	return cnt==n;
    }
    int main(void)
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		insert(x,y);
    		indeg[y]++;
    	}
    	topsort();
    	if(loop)printf("Impossible
    ");
    	else
    		for(int i=1;i<=n;i++)
    			printf("%d ",ans[i]);
    	puts("");
    	return 0;
    }
    

    <后记>

  • 相关阅读:
    第十一次作业
    第十次作业
    第九次作业
    第八次作业
    第七次作业
    第六次作业
    Springboot 2.x 使用 Druid 数据源
    @ConditionalOnMissingBean、@Import 组合使用
    Springboot 2.x 整合 JDBC
    IDEA org.apache.maven.plugins:maven-jar-plugin 报红
  • 原文地址:https://www.cnblogs.com/Parsnip/p/10397610.html
Copyright © 2011-2022 走看看