• BZOJ4727: [POI2017]Turysta tarjan/竞赛图哈密顿


    首先竞赛图保证是一定有哈密顿路径的,强连通的竞赛图一定有哈密顿回路

    竞赛图求每个点的最长链,不重复经过点

    思路就是对每个scc求出哈密顿回路,再按拓扑序n^2dp一下

    哈密顿路径和哈密顿回路的构造法看的这篇文章Bfk_

    #include<bits/stdc++.h>  
    //#pragma comment(linker, "/STACK:1024000000,1024000000")   
    #include<stdio.h>  
    #include<algorithm>  
    #include<queue>  
    #include<string.h>  
    #include<iostream>  
    #include<math.h>                    
    #include<stack>
    #include<set>  
    #include<map>  
    #include<vector>  
    #include<iomanip> 
    #include<bitset>
    using namespace std;         //
    
    #define ll long long  
    #define ull unsigned long long
    #define pb push_back  
    #define FOR(a) for(int i=1;i<=a;i++) 
    #define sqr(a) (a)*(a)
    #define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))
    ll qp(ll a,ll b,ll mod){
    	ll t=1;while(b){if(b&1)t=t*a%mod;b>>=1;a=a*a%mod;}return t;
    }
    struct DOT{ll x;ll y;};
    //inline void read(int &x){int k=0;char f=1;char c=getchar();for(;!isdigit(c);c=getchar())if(c=='-')f=-1;for(;isdigit(c);c=getchar())k=k*10+c-'0';x=k*f;} 
    const int dx[4]={0,0,-1,1};
    const int dy[4]={1,-1,0,0};
    const int inf=0x3f3f3f3f; 
    const ll Linf=0x3f3f3f3f3f3f3f3f;
    const ll mod=1e9+7;;
    
    const int maxn=2e3+43;
    
    int n,g[maxn][maxn];
    
    int dfn[maxn],low[maxn],Time,S[maxn],ins[maxn],top,belong[maxn];
    int cnt,root[maxn];	//scc数量,scc至高点
    int tot,V[maxn];//scc.size
    int nxt[maxn];
    
    int pre[maxn],to[maxn][maxn],du[maxn];
    int q[maxn];
    int dp[maxn];
    
    void get(){	//scc内路径
    	//造哈密顿路径
    	int head=V[1];int tail=V[1];
    	if(tot==1){nxt[tail]=tail;return;}
    	for(int j=2;j<=tot;j++){
    		int i=V[j];
    		if(g[i][head]){nxt[i]=head;head=i;continue;}
    		else if(g[tail][i]){nxt[tail]=i;tail=i;continue;}
    		int x,y;
    		for(x=nxt[head],y=head;x&&!g[i][x];y=x,x=nxt[x]);
    		nxt[y]=i;nxt[i]=x;
    	}
    	//造哈密顿回路
    	tail=head;head=0;
    	for(int i=nxt[tail];i;i=nxt[i]){
    		if(head){
    			for(int p1=head,p2=tail;;p2=p1,p1=nxt[p1]){
    				if(g[i][p1]){
    					nxt[p2]=nxt[tail];
    					if(p2!=tail)nxt[tail]=head;
    					tail=i;head=p1;break;
    				}
    				if(p1==tail)break;
    			}
    		}
    		else if(g[i][tail]){head=tail;tail=i;}
    	}
    	nxt[tail]=head;
    }
    
    void dfs(int u){
    	Time++;dfn[u]=low[u]=Time;
    	ins[u]=1;S[++top]=u;
    	for(int v=1;v<=n;v++)if(g[u][v]){
    		if(!dfn[v]){dfs(v);low[u]=min(low[u],low[v]);}
    		else if(ins[v])low[u]=min(low[u],dfn[v]);
    	}
    	if(low[u]==dfn[u]){
    		cnt++;root[cnt]=u;tot=0;
    		while(1){
    			dp[cnt]++;V[++tot]=S[top];
    			belong[S[top]]=cnt;ins[S[top]]=0;
    			top--;if(S[top+1]==u)break;
    		}
    		get();
    	}
    }
    
    void print(int x){
    	if(!x){printf("
    ");return;}
    	printf("%d ",x);
    	for(int i=nxt[x];i!=x;i=nxt[i])printf("%d ",i);
    	print(root[pre[belong[x]]]);
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<n;i++)for(int j=1;j<=i;j++){
    		int x;scanf("%d",&x);
    		if(x)g[j][i+1]=1;
    		else g[i+1][j]=1;
    	}
    	for(int i=1;i<=n;i++)if(!dfn[i])dfs(i);
    	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){
    		if(g[i][j] && belong[i]!=belong[j])to[belong[i]][belong[j]]=1;
    	}
    	for(int i=1;i<=cnt;i++){
    		for(int j=1;j<=cnt;j++){
    			if(i!=j&&to[j][i])du[i]++;
    		}
    	}
    	int lf=1,rg=0;top=0;
    	for(int i=1;i<=cnt;i++)if(du[i]==0)S[++rg]=i;	//无入度
    	while(lf<=rg){
    		int x=q[++top]=S[lf];lf++;	//压入q栈从叶子dp
    		for(int y=1;y<=cnt;y++){
    			if(!to[x][y]||y==x)continue;
    			du[y]--;if(du[y]==0)S[++rg]=y;
    		}
    	}
    	for(int i=top;i>=1;i--){
    		int x=q[i];int det=0;
    		for(int y=1;y<=cnt;y++){
    			if(!to[x][y]||x==y)continue;
    			if(det<dp[y]){det=dp[y];pre[x]=y;}
    		}
    		dp[x]+=det;
    	}
    	for(int i=1;i<=n;i++){
    		printf("%d ",dp[belong[i]]);
    		print(i);
    	}
    }
    

  • 相关阅读:
    [LUOGU] 1364 医院设置
    [POJ] 3278 Catch That Cow
    [OpenJudge] 2727 仙岛寻药
    [POJ] 2386 Lake Counting
    [POJ]1118 Lining up
    [LUOGU]1141 01迷宫
    [POJ]1111 Image Perimeters
    python之路——初识函数
    python----------文件操作
    Python中的split()函数的用法
  • 原文地址:https://www.cnblogs.com/Drenight/p/8611193.html
Copyright © 2020-2023  润新知