JDOJ 1070: phoneline

JDOJ 1070: phoneline

JDOJ传送门

Description

小h最近准备给家里新装条电话线,好让他在奥运假期能够天天上网冲浪,不用再忍受那昂贵的无线上网。 电信局的工作人员对小h说,电话线网络上有n个站点,它们用m条边来连接,小h家的站点在1号,连接的终点在n号,站点之间有电线连接,而且有一定的费用,然后因为暑期的原因,在1号站点连接到n号站点的线路上有k条线是免费的,然后在这条线路剩下的线中费用最大的为小h连接到n号站要付的费用。 当然,小h希望他要付的钱最少,于是他就出了这道题,希望有人能帮帮他。

Input

第一行: n,m,k,意义如上文所述。(1<n<=1000,1<m<=n*(n-1)/2)
以下m行,每行3个正整数s,t,cost,指从s站到t站的费用是cost.(即t到s的费用也是cost)
1<s,t<=n,0<=cost<=10000
注意:可能会出现重边或自环

Output

一个正整数,表示最小的费用。

Sample Input

5 6 1 2 1 3629 3 2 8034 4 3 7348 5 4 3689 4 4 7266 5 5 6088

Sample Output

7348


题解:

和运输计划这道题的思路有些同源(其实差距还是蛮大的)

一看到最长路最短想二分答案。

判断当前答案是否合法的思路:把全图所有比当前答案大的边全部打上标记,统计从1到n最少能经过多少条带标记的边,如果大于k,就不合法,小于k,就合法了。

如何统计“最少经过多少条带标记的边呢”?很简单,新建一个边权数组跑最短路即可。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define R register
using namespace std;
const int maxn=1010;
const int maxm=5*1e5;
int n,m,k,maxx;
bool v[maxn];
int dist[maxn];
int tot,to[maxm<<1],nxt[maxm<<1],val[maxm<<1],head[maxn],val1[maxm<<1];
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
inline int read()
{
    int x=0,f=1;
    char ch=nc();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=nc();
    }
    while(ch>='0'&&ch<='9')
        x=x*10+ch-'0',ch=nc();
   	return x*f;
}
inline void add(int x,int y,int z)
{
	to[++tot]=y;
	nxt[tot]=head[x];
	val[tot]=z;
	head[x]=tot;
}
inline void dijkstra(int start)//源点
{
    int temp,k,y;
    memset(dist,0x3f,sizeof(dist));
    memset(v,0,sizeof(v));
    dist[start]=0;
    for(R int i=1;i<=n;i++)
    {
        temp=1<<30;
        for(R int j=1;j<=n;j++)
            if(dist[j]<temp && v[j]==0)
                k=j,temp=dist[j];
        v[k]=1;
        for(R int j=head[k];j;j=nxt[j])
        {
            y=to[j];
            if(dist[y]>dist[k]+val1[j])
                dist[y]=dist[k]+val1[j];
        }
	}
}
inline void dfs(int d)
{
	for(R int i=1;i<=n;i++)
		for(R int j=head[i];j;j=nxt[j])
			if(val[j]>d)
				val1[j]=1;
}
inline bool check(int x)
{
	memset(val1,0,sizeof(val1));
	dfs(x);
	dijkstra(1);
	return dist[n]>k?0:1;
}
int main()
{
	n=read();m=read();k=read();
	for(R int i=1;i<=m;i++)
	{
		int x,y,z;
		x=read();y=read();z=read();
		add(x,y,z);
		add(y,x,z);
		maxx=max(maxx,z);
	}
	int l=0,r=maxx;
	while(l<r)
	{
		int mid=(l+r)>>1;
		if(check(mid))
			r=mid;
		else
			l=mid+1;
	}
	printf("%d",l);
	return 0;
}
原文地址:https://www.cnblogs.com/fusiwei/p/13752908.html