图中的最长环
Posted 929code
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图中的最长环相关的知识,希望对你有一定的参考价值。
给你一个 n 个节点的 有向图 ,节点编号为 0 到 n - 1 ,其中每个节点 至多 有一条出边。
图用一个大小为 n 下标从 0 开始的数组 edges 表示,节点 i 到节点 edges[i] 之间有一条有向边。
如果节点 i 没有出边,那么 edges[i] == -1 。
1. 深度优先搜索
同时记录已遍历的进行剪枝
class Solution
public:
int longestCycle(vector<int>& edges)
int res = -1;
int n = edges.size();
vector<int> pathval(n);
for(int i=0;i<n;i++)//遍历所有节点找环
if(edges[i]<0) continue;//没有出边,或已经遍历过
int cur = i; int val = 1;
vector<int> visit;
while(cur>=0)//递归到没有下一个顶点
visit.push_back(cur);//加入已遍历节点中
if(edges[cur]<0) break;//下一节点已遍历,跳出循环,剪枝
if(pathval[cur]>0)
res = max(res,val-pathval[cur]);//计算环的长度
break;//这次循环遍历过
pathval[cur] = val;//顶点赋权值
val++;//权值增加
cur= edges[cur];//移动到下一节点
for(int index:visit)
edges[index] = -1;//将已遍历的置为-1
return res;
;
2. 更优雅的写法
运用全局时间戳,减少判断
class Solution
public:
int longestCycle(vector<int> &edges)
int n = edges.size();
int res = -1;
vector<int> time(n);
for (int i = 0, clock = 1; i < n; i++) //遍历n个顶点
if (time[i]) continue; //已经遍历过跳过
for (int x = i, start_time = clock; x >= 0; x = edges[x]) //递归到没有下一个顶点
if (time[x]) // 重复访问
if (time[x] >= start_time) // 找到了一个新的环,关键语句,全局时间戳,避免将原来遍历过的视为环
res = max(res, clock - time[x]);
break;
time[x] = clock++;//标记
return res;
;
hdu4514(非连通图的环判断与图中最长链)(树的直径)
湫湫系列故事——设计风景线
随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,那就建的越长越好。
现在已经勘探确定了n个位置可以用来建设,在它们之间也勘探确定了m条可以设计的路线以及他们的长度。请问是否能够建成环形的风景线?如果不能,风景线最长能够达到多少?
其中,可以兴建的路线均是双向的,他们之间的长度均大于0。
现在已经勘探确定了n个位置可以用来建设,在它们之间也勘探确定了m条可以设计的路线以及他们的长度。请问是否能够建成环形的风景线?如果不能,风景线最长能够达到多少?
其中,可以兴建的路线均是双向的,他们之间的长度均大于0。
Input 测试数据有多组,每组测试数据的第一行有两个数字n, m,其含义参见题目描述;
接下去m行,每行3个数字u v w,分别代表这条线路的起点,终点和长度。
[Technical Specification]
1. n<=100000
2. m <= 1000000
3. 1<= u, v <= n
4. w <= 1000
Output 对于每组测试数据,如果能够建成环形(并不需要连接上去全部的风景点),那么输出YES,否则输出最长的长度,每组数据输出一行。
Sample Input
3 3 1 2 1 2 3 1 3 1 1
Sample Output
YES
题解:就是判环,如果无环的话就求出树的直径,如果有环的话就输出YES,就可以了,记录一个最
长路,和次长路,就ok了。
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #define N 100007 8 #define M 1000007 9 using namespace std; 10 11 int n,m,ans; 12 int cnt,head[N],Next[M*2],rea[M*2],val[M*2]; 13 int f[N][3],fa[N]; 14 bool vis[N]; 15 16 void Add(int u,int v,int fee){Next[++cnt]=head[u],head[u]=cnt,rea[cnt]=v,val[cnt]=fee;} 17 int find(int num) 18 { 19 if (fa[num]!=num) return fa[num]=find(fa[num]); 20 return fa[num]; 21 } 22 void dfs_solve(int u,int fa) 23 { 24 for (int i=head[u];i!=-1;i=Next[i]) 25 { 26 int v=rea[i],fee=val[i]; 27 if (v==fa||vis[v]) continue; 28 vis[v]=1;dfs_solve(v,u); 29 if (f[v][1]+fee>f[u][1]) 30 { 31 f[u][2]=f[u][1]; 32 f[u][1]=f[v][1]+fee; 33 } 34 else if (f[v][1]+fee>f[u][2]) f[u][2]=f[v][1]+fee; 35 } 36 ans=max(ans,f[u][1]+f[u][2]); 37 } 38 int main() 39 { 40 while (~scanf("%d%d",&n,&m)) 41 { 42 ans=cnt=0; 43 bool flag=0; 44 memset(vis,0,sizeof(vis)); 45 memset(head,-1,sizeof(head)); 46 memset(f,0,sizeof(f)); 47 for (int i=1;i<=n;i++) fa[i]=i; 48 for (int i=1,x,y,z;i<=m;i++) 49 { 50 scanf("%d%d%d",&x,&y,&z); 51 if (flag) continue; 52 int u=find(x),v=find(y); 53 if (u==v) 54 { 55 flag=1; 56 printf("YES\n"); 57 } 58 else fa[u]=v; 59 Add(x,y,z),Add(y,x,z); 60 } 61 if (flag) continue; 62 ans=-1; 63 for (int i=1;i<=n;i++) 64 { 65 if (!vis[i]) 66 { 67 vis[i]=1; 68 dfs_solve(i,-1); 69 } 70 } 71 printf("%d\n",ans); 72 } 73 }
以上是关于图中的最长环的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ.1023.[SHOI2008]cactus仙人掌图(DP)