• Codeforces 2014-2015 ACM-ICPC, NEERC, Southern Subregional Contest L. Useful Roads


    L. Useful Roads
    time limit per test:4 seconds
    memory limit per test:512 megabytes
    input:standard input
    output:standard output

    Berland capital contains n junctions and m roads connecting pairs of junctions. All roads are one-way. As you probably know Berland has two misfortunes: fools and roads.

    It is one month before mayoral election. So it is time for current government to make the city better. To show that they care both about the infrastructure and about the budget, the government decided to repair only useful roads.

    Current mayor thinks that a road from a junction u to a junction v is useful if there exists a simple path from City Hall to some junction containing the road (u, v). A path is called simple if it does not have any repeated junctions, i.e. contains each junction at most once. The City Hall is located at the junction 1.

    Help Ministry of Road Transport and Highways to find all useful roads in the city.

    Input

    The input contains several test cases. Each test case starts with a line containing two integers nm (2 ≤ n ≤ 2·105;1 ≤ m ≤ 2·105) — the number of junctions and the number of roads in the city. The following m lines contain road descriptions, one description per line. A description consists of a pair of space-separated integers uivi (1 ≤ ui, vi ≤ n;ui ≠ vi) meaning that the i-th road leads from the junction ui to the junction vi. The junctions are numbered from 1 to n. The City Hall is located at the junction 1.

    It is guaranteed that there is at most one road between a pair of junctions in each direction.

    There is a blank line after each test case. The sum of n over all test cases in the input doesn't exceed 2·105. The same is true for m: the sum of m over all test cases in the input doesn't exceed 2·105.

    Output

    Print two lines for each test case. On the first line print the number of useful roads. The second line should contain the indices of useful roads in ascending order. The roads are indexed from 1 to m in order of appearance in the input. Leave the second line empty if there are no useful roads in the city.

    Examples
    input
    5 7
    1 2
    5 2
    2 3
    3 4
    4 5
    2 4
    4 2


    2 1
    1 2

    output
    5
    1 3 4 5 6
    1
    1

    题意:

    给出一张有向图(不保证联通...),判断那些边是有用的边...

    有用边的定义:有一条从1号节点出发的简单路径覆盖这条边...

    分析:

    画画图想一想就会发现如果存在一条边(x,y),那么这是一条有用边当且仅当从1出发可以到达xy并且y不是x的必经点...

    然后建出支配树来判断y是否是x的祖先就好了...

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<stack>
    //by NeighThorn
    using namespace std;
    
    const int maxn=200000+5;
    
    int n,m,ans,tot,f[maxn],fa[maxn],id[maxn],dfn[maxn],end[maxn],idom[maxn],semi[maxn],node[maxn];
    
    stack<int> dom[maxn];
    
    struct M{
    	
    	int cnt,hd[maxn],to[maxn],nxt[maxn];
    	
    	inline void init(void){
    		cnt=0;
    		memset(hd,-1,sizeof(hd));
    	}
    	
    	inline void add(int x,int y){
    		to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++;
    	}
    	
    }G,tr;
    
    struct L{
    	int x,y,res;
    }e[maxn];
    
    inline int read(void){
    	char ch=getchar();int x=0;
    	while(!(ch>='0'&&ch<='9')) ch=getchar();
    	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    	return x;
    }
    
    inline bool cmp(int x,int y){
    	return dfn[semi[x]]<dfn[semi[y]];
    }
    
    inline int find(int x){
    	if(x==f[x])
    		return x;
    	int fx=find(f[x]);
    	node[x]=min(node[f[x]],node[x],cmp);
    	return f[x]=fx;
    }
    
    inline void dfs(int x){
    	dfn[x]=++tot;id[tot]=x;
    	for(int i=tr.hd[x];i!=-1;i=tr.nxt[i])
    		if(!dfn[tr.to[i]])
    			fa[tr.to[i]]=x,dfs(tr.to[i]);
    }
    
    inline void LT(void){
    	dfs(1);dfn[0]=tot<<1;
    	for(int i=tot,x;i>=1;i--){
    		x=id[i];
    		if(i!=1){
    			for(int j=G.hd[x],v;j!=-1;j=G.nxt[j])
    				if(dfn[G.to[j]]){
    					v=G.to[j];
    					if(dfn[v]<dfn[x]){
    						if(dfn[v]<dfn[semi[x]])
    							semi[x]=v;
    					}
    					else{
    						find(v);
    						if(dfn[semi[node[v]]]<dfn[semi[x]])
    							semi[x]=semi[node[v]];
    					}
    				}
    			dom[semi[x]].push(x);
    		}
    		while(dom[x].size()){
    			int y=dom[x].top();dom[x].pop();find(y);
    			if(semi[node[y]]!=x)
    				idom[y]=node[y];
    			else
    				idom[y]=x;
    		}
    		for(int j=tr.hd[x];j!=-1;j=tr.nxt[j])
    			if(fa[tr.to[j]]==x)
    				f[tr.to[j]]=x;
    	}
    	for(int i=2,x;i<=tot;i++){
    		x=id[i];
    		if(semi[x]!=idom[x])
    			idom[x]=idom[idom[x]];
    	}
    	idom[id[1]]=0;
    }
    
    inline void dfs2(int x){
    	dfn[x]=++tot;
    	for(int i=tr.hd[x];i!=-1;i=tr.nxt[i])
    		dfs2(tr.to[i]);
    	end[x]=tot;
    }
    
    signed main(void){
    #ifndef ONLINE_JUDGE
    	freopen("in.txt","r",stdin);
    #endif
    	while(scanf("%d%d",&n,&m)!=EOF){
    		tr.init();G.init();tot=0;
    		for(int i=1;i<=n;i++)
    			f[i]=node[i]=i,dfn[i]=semi[i]=idom[i]=0;
    		for(int i=1;i<=m;i++)
    			e[i].x=read(),e[i].y=read(),tr.add(e[i].x,e[i].y),G.add(e[i].y,e[i].x);
    		LT();ans=0;tr.init();
    		for(int i=2;i<=tot;i++)
    			tr.add(idom[id[i]],id[i]);
    		tot=0;dfs2(id[1]);
    		for(int i=1,x,y;i<=m;i++){
    			x=e[i].x,y=e[i].y;
    			if(!dfn[x]||!dfn[y])
    				e[i].res=0;
    			else if(dfn[x]>dfn[y]&&dfn[x]<=end[y])
    				e[i].res=0;
    			else
    				e[i].res=1;
    			ans+=e[i].res;
    		}printf("%d
    ",ans);
    		for(int i=1;i<=m;i++)
    			if(e[i].res)
    				printf("%d ",i);
    		puts("");
    	}
    	return 0;
    }
    

      


    By NeighThorn

  • 相关阅读:
    预警|使用方维、微吼等系统直播平台警惕黑客攻击
    常用的商业级和免费开源Web漏洞扫描工具
    现身说法:面对DDoS攻击时该如何防御?
    修改数据库插入默认日期
    SQL Server中Rowcount与@@Rowcount的用法 和set nocount on 也会更新@@Rowcount
    sql存储过程异常捕获并输出例子还有不输出过程里面判断异常 例子
    delphi 判断一个数组的长度用 Length 还是 SizeOf ?
    object_id用法
    SqlServer try catch 捕获不到的一些错误及解决方法(转载)
    sql rank()函数
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6554050.html
Copyright © 2020-2023  润新知