URAL 1227 Rally Championship(树的直径)(无向图判环)

1227. Rally Championship

Time limit: 1.0 second
Memory limit: 64 MB

A
high-level international rally championship is about to be held. The
rules of the race state that the race is held on ordinary roads and the
route has a fixed length. You are given a map of the cities and two-way
roads connecting it. To make the race safer it is held on one-way roads.
The race may start and finish anyplace on the road. Determine if it is
possible to make a route having a given length S.

Input

The first line of the input contains integers M, N and S that are the number of cities, the number of roads the length of the route (1 ≤ M ≤ 100; 1 ≤ N ≤ 10 000; 1 ≤ S ≤ 2 · 106).

The following N lines describe the roads as triples of integers: P, Q, R. Here P and Q are cities connected with a road, and R is the length of this road. All numbers satisfy the following restrictions: 1 ≤ P, QM; 1 ≤ R ≤ 32000.

Output

Write
YES to the output if it is possible to make a required route and NO
otherwise. Note that answer must be written in capital Latin letters.

Samples

input output
3 2 20
1 2 10
2 3 5
NO
3 3 1000
1 2 1
2 3 1
1 3 1
YES

Problem Source: 2002-2003 ACM Central Region of Russia Quarterfinal Programming Contest, Rybinsk,

【分析】先判断是否有环,如果有则YES,没有的话找最大直径,如果大于等于s,则YES,其他情况则NO。注意有图不连通情况。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof a)
typedef long long ll;
using namespace std;
const int N = 10005;
const int M = 24005;
int n,m,cnt=0;
int tot=0,s,t,son,sum;
int head[N],dis[N],vis[N],pre[N],vis1[N];
int w[N][N];
int in[N],out[N];
int  bfs(int x) {
    met(vis,0);
    met(dis,0);
    sum=0;
    queue<int>Q;
    Q.push(x);
    vis[x]=1;vis1[x]=1;
    while(!Q.empty()) {
        int t=Q.front();
        Q.pop();//printf("t=%d\n",t);
        bool has=false;
        for(int i=1; i<=n; i++) {
            if(!vis[i]&&w[t][i]!=0) {
                Q.push(i);
                dis[i]=dis[t]+w[t][i];
                vis[i]=vis1[i]=1;
                has=true;
            }
        }
        if(!has) {
            if(dis[t]>sum) {
                sum=dis[t];
                //printf("%d %d\n",sum,dis[t]);
                son=t;
            }
        }
    }
    return sum;
}
int main() {
    int u,v,l,sum=0;
    scanf("%d%d%d",&n,&m,&s);
    while(m--) {
        scanf("%d%d%d",&u,&v,&l);
        w[u][v]=w[v][u]=l;
        in[u]++;
        in[v]++;
    }
    queue<int>q;
    for(int i=1; i<=n; i++) {
        if(in[i]<=1)q.push(i);
    }
    while(!q.empty()) {
        int t=q.front();
        q.pop();
        vis[t]=1;
        for(int i=1; i<=n; i++) {
            if(!vis[i]&&w[t][i]!=0) {
                in[i]--;
                if(in[i]==1)q.push(i);
            }
        }
    }
    bool flag=false;
    for(int i=1; i<=n; i++) {
        if(!vis[i])flag=true;
    }
    if(flag)printf("YES\n");
    else {
        int ans=-1;
        memset(vis1,0,sizeof vis1);
        for(int i=1; i<=n; i++)
            if(!vis1[i]) {
                bfs(i);
                ans=max(ans,bfs(son));
            }
        if(ans>=s)puts("YES");
        else puts("NO");
    }
    return 0;
}
时间: 2024-10-18 02:32:53

URAL 1227 Rally Championship(树的直径)(无向图判环)的相关文章

URAL 1752. Tree 2 树的直径+LCA倍增

题目来源:URAL 1752. Tree 2 题意:求一个点v与它距离为d的任意一个点 没有输出0 思路:开始想倍增法 但是倍增法只能往他的祖先去 后来百度发现了树的直径 想了想 发现可以建2棵树 每一棵树的根是树的直径的2个端点 这样保证了每个点和他距离最远的点就是其中一个根 因为一个点到树的直径的端点的距离是最远的 最后就是LCA倍增了 #include <cstdio> #include <cstring> #include <algorithm> #includ

URAL 1752 Tree 2 树的直径与倍增

假设树的直径的两个端点为p0,p1.如果对于一次询问(v,k)存在点q满足要求,那么q必然在v到p0或v到p1的路径上. 剩下的就是在树上寻找p了.倍增就好了. #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #

HDU 1272 小希的迷宫 (无向图判环)

题意:给出一张无向图,判定是否有环,判定是否为一棵树: 思路:并查集判环,唯一祖先: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define M 0x3f3f3f3f int fa[500010],mark[500010]; void init() { for(int i=0;i<=500010;i++) fa[i]=i; } int fin(int x

hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径

题意如上,含有重边(重边的话,俩个点就可以构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选任意起点U,进行bfs,到达最远的一个点v(level最深)该点必然是树的直径的一个端点,,再从该点出发,bfs,到最深的一点,该点深度就是直径.(证明:先假设u,是直径上一点,S,T是直径的端点,设v!=t,则有(V,U)+(U,S)>(T,U)+(U,S),矛盾,故t=v:若u不是直径上一点,设u到直径上的一点为x,同理易证. 最后 缩

hdu4612 无向图中随意加入一条边后使桥的数量最少 / 无向图缩点+求树的直径

题意如上,含有重边(重边的话,俩个点就能够构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选随意起点U,进行bfs,到达最远的一个点v(level最深)该点必定是树的直径的一个端点,,再从该点出发,bfs,到最深的一点.该点深度就是直径. (证明:先如果u.是直径上一点,S,T是直径的端点.设v!=t,则有(V,U)+(U,S)>(T,U)+(U,S),矛盾,故t=v:若u不是直径上一点.设u到直径上的一点为x.同理易证. 最后

ural 1145 Rope in the Labyrinth 图中 bfs求树的直径

1145. Rope in the Labyrinth Time limit: 0.5 second Memory limit: 64 MB A labyrinth with rectangular form and size m × n is divided into square cells with sides' length 1 by lines that are parallel with the labyrinth's sides. Each cell of the grid is

HDU 4612——Warm up——————【边双连通分量、树的直径】

Warm up Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4612 Description N planets are connected by M bidirectional channels that allow instant transportation. It's always possible to travel bet

(求树的直径)Warm up -- HDU -- 4612

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 给一个无向图, 加上一条边后,求桥至少有几个: 那我们加的那条边的两个顶点u,v:一定是u,v之间含有桥的数量最多,然后uv之间的桥都没了,剩下的就是要求的结果: 树的直径的定义刚好就是两个节点之间含有最多的边: 下面是有关树的直径的知识: 这个题目需要手动扩展,不然会爆栈,而且手动扩展的话要用C++提交. 代码: #pragma comment(linker, "/STACK:1024000

树的直径

*总结的别人博客 树的直径(Diameter)是指树上的最长简单路.直径的求法:两遍BFS (or DFS)任选一点u为起点,对树进行BFS遍历,找出离u最远的点v以v为起点,再进行BFS遍历,找出离v最远的点w.则v到w的路径长度即为树的直径*简单证明于是原问题可以在O(E)时间内求出 关键在于证明第一次遍历的正确性,也就是对于任意点u,距离它最远的点v一定是最长路的一端.如果u在最长路上,那么v一定是最长路的一端.可以用反证法:假设v不是最长路的一端,则存在另一点v’使得(u→v’)是最长路