zoukankan      html  css  js  c++  java
  • [Luogu] CF117C Cycle

    (Link)

    Description

    给出一个竞赛图(每两个点之间都有一条有向边),试找出图中的一个三元环,若不存在输出(-1)((nle5000))

    Solution

    注意到竞赛图如果有一个大环,那么中间一定会有三元环。这是比较好证明的。(下面是蒯的)

    假设一个竞赛图存在一个(N)元环(大于三元),环上有连续三点(A , B , C)( 存在有向边(AB , BC)

    根据竞赛图的定义,一定存在有向边(CA)(AC)中的一者。

    情况(1):若存在(CA),则(A , B , C)构成三元环;

    情况(2):若存在(AC) ,不考虑(B)点,剩下的点构成一个((N-1))元环。显然,如果一直不存在情况(1)的话,最终也会形成一个三元环。

    这个在纸上自己模拟一下就好了。

    所以我们用(Tarjan)找出图中每一个强连通分量。注意到对于中间的某个点对((A,B)),假设它们在原图上的边是(A ightarrow{B}),又因为(B)也可以到(A),所以(A)(B)一定在同一个大环内。所以我们枚举其中每个点对((A,B)),再钦定某个强连通分量内的点(x),因为(A)(B)一定在同一个大环内,模拟找三元环的过程,就一定可以找出一个三元环((A,B,x))

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int n, t, top, ind, low[5005], dfn[5005], que[5005], vis[5005], rec[5005];
    
    char ch[5005][5005];
    
    int read()
    {
    	int x = 0, fl = 1; char ch = getchar();
    	while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
    	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
    	return x * fl;
    }
    
    void Tarjan(int x)
    {
    	dfn[x] = low[x] = ++ ind;
    	vis[x] = 1;
    	que[ ++ top] = x;
    	for (int y = 1; y <= n; y ++ )
    	{
    		if (ch[x][y] != '1') continue;
    		if (!dfn[y])
    		{
    			Tarjan(y);
    			low[x] = min(low[x], low[y]);
    		}
    		else if (vis[y]) low[x] = min(low[x], dfn[y]);
    	}
    	if (low[x] == dfn[x])
    	{
    		t = 0;
    		int now = -1;
    		do
    		{
    			now = que[top -- ];
    			vis[now] = 0;
    			rec[ ++ t] = now;
    		} while (now != x);
    		for (int i = 1; i <= t - 1; i ++ )
    		{
    			for (int j = 1; j <= t - 1; j ++ )
    			{
    				if (ch[x][rec[i]] == '1' && ch[rec[i]][rec[j]] == '1' && ch[rec[j]][x] == '1' && i != j)
    				{
    					printf("%d %d %d
    ", x, rec[i], rec[j]);
    				    exit(0);
    				}
    			}
    		}
    	}
    	return;
    }
    
    int main()
    {
    	n = read();
    	for (int i = 1; i <= n; i ++ )
    		scanf("%s", ch[i] + 1);
    	for (int i = 1; i <= n; i ++ )
    		if (!dfn[i])
    			Tarjan(i);
    	puts("-1");
    	return 0;
    }
    
  • 相关阅读:
    一:理解ASP.NET的运行机制(例:通过HttpModule来计算页面执行时间)
    解决Silverlight F5刷新问题
    C# 将 HTML 转换为图片或 PDF
    C# 使用 Windows API 发送文件到打印机
    C# 各种导入 Excel 文件的数据的方法总结
    C# 使用 SqlBulkCopy 类批量复制数据到数据库
    C# 导出 Excel 的各种方法总结
    C# 使用windows服务发送邮件
    C# 创建、部署和调用WebService的简单示例
    SQL Server 常用函数使用方法(持续更新)
  • 原文地址:https://www.cnblogs.com/andysj/p/14014551.html
Copyright © 2011-2022 走看看