Graph

Graph
( graph .cpp/c/pas)
Description
小 Y 又开始了一段旅途。
这次,他要经过一个图,从1号点到达n号点,每个点设有休息站。
小 Y 计划用最多k天走完全程,除第k天外,每一天小 Y 都必须在休息站过夜。所以,一段路必须在同一天走完。
小 Y 的体力有限,他希望走的路程最大的一天中走的路尽可能少,请求出这个最小值。
Input
第一行三个整数n、m、k表示图的顶点数、边数、天数。
从第二行开始,之后的m行,每行三个整数ui、vi、wi表示从ui和vi间有一条双向道路,长度为wi。
Output
一行一个正整数,如果小 Y 能走完全程,输出走的路程最大的一天中走的路程最小值,否则输出-1。
Example
graph.in
3 2 4
3 2 4
1 2 1
graph.out
4
附加样例见选手目录下『graph』文件夹。
Hint
对于10%的数据,m=0;
对于30%的数据,n,m,k<=10 ;
对于100%的数据,2<=n<=k<=7500,0<=m<=200000,1<=wi<=10^9;
保证没有重边和自环。

 【题目分析】

 开始想的是用dijkstra,算一下时间应该不会超(我觉得....),但据说空间会爆?

好吧,正解思路:并查集+二分答案,先找到最大的边权值为右端点,然后二分查找,去掉比找到的答案大的边

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Node{
    int T,T1,T2;
}a[200001];
int m,n,k,ans=-1,F[7501];
int Find(int t)
{
    if (F[t]==t)
      return t;
    return F[t]=Find(F[t]);
}
bool Check(int t)
{
    for (int i=1;i<=n;i++)
      F[i]=i;
    for (int i=1;i<=m;i++)
    {
          if (a[i].T>t)
            continue;
          int t1=Find(a[i].T1);
          int t2=Find(a[i].T2);
          if (t1!=t2)
            F[t2]=t1;
          if (Find(1)==Find(n))
            return true;
    }
    return false;
}
int main()
{
    //freopen("graph.in","r",stdin);
    //freopen("graph.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    int maxn=0;
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&a[i].T1,&a[i].T2,&a[i].T);
        maxn=max(maxn,a[i].T);
    }
    int Left=0,Right=maxn;
    while (Left<=Right)
    {
        int Mid=(Left+Right)>>1;
        if (Check(Mid))
        {
            ans=Mid;
            Right=Mid-1;
        }
        else
          Left=Mid+1;
    }
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/xiaoningmeng/p/5794288.html