zoukankan      html  css  js  c++  java
  • 洛谷 [P2661] 信息传递

    求有向图的权值为一的最小环##

    并查集做法####

    维护一个dis[],表示i号元素到fa[i]的距离。
    对于输入的每两个点u,v,询问这两个点的fa[]是否相同,如果相同就成环,维护最小值,mi=min(mi,dis[u]+dis[v]+1)。如果不相同,merge(u,v)。目测是最简单的做法。
    但是只适用于权值为一的边。
    注意对于一条U指向v的边,是将u合并到v上。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    const int MAXN=200005;
    int read(){
    	int rv=0,fh=1;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		if(c=='-') fh=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		rv=(rv<<1)+(rv<<3)+c-'0';
    		c=getchar();
    	}
    	return rv*fh;
    }
    int fa[MAXN],n,mi=0x7fffffff/3,dis[MAXN];
    int find(int x){
    	if(x!=fa[x]) {
    		int t=fa[x];fa[x]=find(fa[x]);dis[x]+=dis[t];
    	}
    	return fa[x];
    }
    void merge(int x,int y){
    	int r1=find(x),r2=find(y);
    	if(r1!=r2){
    		fa[r1]=r2;
    		dis[x]=dis[y]+1;
    	}
    }
    int main(){
    	freopen("in.txt","r",stdin);
    	n=read();
    	for(int i=1;i<=n;i++){
    		fa[i]=i;
    	}
    	for(int i=1;i<=n;i++){
    		int t=read();
    		if(find(i)==find(t)){
    			mi=min(mi,dis[i]+dis[t]+1);
    		}else {
    			merge(i,t);
    		}
    	}
    	cout<<mi;
    	fclose(stdin);
    	return 0;
    }
    
    

    topsort####

    使用拓扑排序删掉那些一定不属于环上的点,再用dfs更新最小环的数量。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    using namespace std;
    const int MAXN=200005;
    int read(){
    	int rv=0,fh=1;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		if(c=='-') fh=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		rv=(rv<<1)+(rv<<3)+c-'0';
    		c=getchar();
    	}
    	return rv*fh;
    }
    struct edge{
    	int to,nxt;
    }e[MAXN];
    int n,head[MAXN],nume,in[MAXN],f[MAXN],mi=0x7fffffff/3,cnt;
    void adde(int from,int to){
    	e[++nume].to=to;
    	e[nume].nxt=head[from];
    	head[from]=nume;
    }
    queue<int> q;
    void dfs(int u){
    	cnt++;
    	f[u]=1;
    	for(int i=head[u];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(!f[v]) dfs(v);
    	}
    }
    int main(){
    	freopen("in.txt","r",stdin);
    	n=read();
    	for(int i=1;i<=n;i++){
    		int t=read();
    		adde(i,t);
    		in[t]++;
    	}
    	for(int i=1;i<=n;i++){
    		if(!in[i]){
    			q.push(i),f[i]=1;
    		}
    	}
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int i=head[u];i;i=e[i].nxt){
    			int v=e[i].to;
    			in[v]--;
    			if(!in[v]&&!f[v]){
    				q.push(v);f[v]=1;
    			}
    		}
    	}
    	for(int i=1;i<=n;i++){
    		cnt=0;
    		if(!f[i]) {dfs(i);mi=min(mi,cnt);}
    		
    	}
    	cout<<mi;
    	fclose(stdin);
    	return 0;
    }
    
    

    tarjan求强连通分量####

    最小环即强连通分量

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    using namespace std;
    const int MAXN=200005;
    int read(){
    	int rv=0,fh=1;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		if(c=='-') fh=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		rv=(rv<<1)+(rv<<3)+c-'0';
    		c=getchar();
    	}
    	return rv*fh;
    }
    struct edge{
    	int to,nxt;
    }e[MAXN];
    int n,head[MAXN],nume,dfn[MAXN],low[MAXN],in,mi=0x7fffffff/3;
    stack <int>s;
    bool f[MAXN];
    void adde(int from,int to){
    	e[++nume].to=to;
    	e[nume].nxt=head[from];
    	head[from]=nume;
    }
    void tarjan(int u){
    	dfn[u]=++in;
    	low[u]=++in;
    	f[u]=1;
    	s.push(u);
    	for(int i=head[u];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(!dfn[v]){
    			tarjan(v);
    			low[u]=min(low[u],low[v]);
    		}else if(f[v]){
    			low[u]=min(low[u],dfn[v]);
    		}
    	}
    	if(dfn[u]==low[u]){
    		int v=0;
    		int cnt=0;
    		do{
    			v=s.top();
    			s.pop();
    			f[v]=0;
    			cnt++;
    		}while(v!=u);
    		mi=min(mi,cnt);
    	//	cout<<u<<" "<<cnt<<endl;
    	}
    }
    int main(){
    	freopen("in.txt","r",stdin);
    	n=read();
    	for(int i=1;i<=n;i++){
    		int t=read();
    		adde(i,t);
    	}
    	for(int i=1;i<=n;i++){
    		if(!dfn[i]) tarjan(i);
    	}
    	cout<<mi;
    	fclose(stdin);
    	return 0;
    }
    
    
  • 相关阅读:
    suse12安装详解
    Centos7上部署openstack mitaka配置详解(将疑难点都进行划分)
    菜鸟帮你跳过openstack配置过程中的坑[文末新添加福利]
    openstack中dashboard页面RuntimeError: Unable to create a new session key. It is likely that the cache is unavailable.
    Multiple network matches found for name 'selfservice', use an ID to be more specific.报错
    查看 SELinux状态及关闭SELinux
    SELinux深入理解
    IP地址、子网掩码、网络号、主机号、网络地址、主机地址
    Oracle job procedure 存储过程定时任务
    POI文件导出至EXCEL,并弹出下载框
  • 原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/7868331.html
Copyright © 2011-2022 走看看