1117: [视频]网络流入门3:路径中的最长边最小
时间限制: 2 Sec 内存限制: 128 MB提交: 169 解决: 58
[ 提交][ 状态][ 讨论版]
题目描述
【题目描述】
千万要注意两个概念:边 和 路径(路径是由多条边组成,当然可以是一条边)
给出N(2 <= N <= 200)个点和P(1 <= P <= 40,000)条双向边,每条边的长度为(0~1 000 000),现在要求选出T(1 <= T <= 200)条“1至N”的路径, 任意两条路径上的边不能重复 ,并且要求这些路径中的 最长边 的长度最小。注意:两个点之间有可能多条边,出发点是1,终点是N。
【输入格式】
第一行三个整数: N, P, and T 。
下来P行,每行三个整数 x, y, L,描述一条边:从点x到y的双向边,长度为Li。
【输出格式】
求这T条路径中的的最长边的最小值。
Sample Input
7 9 2
1 2 2
2 3 5
3 7 5
1 4 1
4 3 1
4 5 7
5 7 1
1 6 3
6 7 3
Sample Output
5
提示:样例最后选择了两条路径 1 - 2 - 3 - 7 and 1 - 6 - 7.最长的路是5.
数据很多,要用scanf读,用cin会超时
千万要注意两个概念:边 和 路径(路径是由多条边组成,当然可以是一条边)
给出N(2 <= N <= 200)个点和P(1 <= P <= 40,000)条双向边,每条边的长度为(0~1 000 000),现在要求选出T(1 <= T <= 200)条“1至N”的路径, 任意两条路径上的边不能重复 ,并且要求这些路径中的 最长边 的长度最小。注意:两个点之间有可能多条边,出发点是1,终点是N。
【输入格式】
第一行三个整数: N, P, and T 。
下来P行,每行三个整数 x, y, L,描述一条边:从点x到y的双向边,长度为Li。
【输出格式】
求这T条路径中的的最长边的最小值。
Sample Input
7 9 2
1 2 2
2 3 5
3 7 5
1 4 1
4 3 1
4 5 7
5 7 1
1 6 3
6 7 3
Sample Output
5
提示:样例最后选择了两条路径 1 - 2 - 3 - 7 and 1 - 6 - 7.最长的路是5.
数据很多,要用scanf读,用cin会超时
这是一道典型的网络流题目,很好理解,直接上代码:
#include<cstdio>
#include<cstring>
using namespace std;
struct node
{
int x,y,c,next,other;
}a[81000];int len,last[210],st,ed;
inline void ins(int x,int y,int c)
{
len++;int k1=len;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=last[x];last[x]=len;
len++;int k2=len;
a[len].x=y;a[len].y=x;a[len].c=c;//因为是双向边,所以就不用为0
a[len].next=last[y];last[y]=len;
a[k1].other=k2;
a[k2].other=k1;
}
int head,tail,list[210],h[210];
inline bool bt_h()
{
memset(h,0,sizeof(h));h[st]=1;
list[1]=st;head=1;tail=2;
while(head!=tail)
{
int x=list[head];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(a[k].c>0 && h[y]==0)
{
h[y]=h[x]+1;
list[tail++]=y;
}
}
head++;
}
if(h[ed]>0) return true;
return false;
}
int mymin(int x,int y){return x<y?x:y;}
int findflow(int x,int f)
{
if(x==ed) return f;
int s=0,t;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(a[k].c>0 && h[y]==h[x]+1 && s<f)
{
s+=(t=findflow(y,mymin(a[k].c,f-s)));
a[k].c-=t;a[a[k].other].c+=t;
}
}
if(s==0) h[x]=0;
return s;
}
int x[41000],y[41000],d[41000];int N,M,T;
inline int check(int xx)//求所有长度不大于xx的路径的数量
{
len=0;memset(last,0,sizeof(last));
for(int i=1;i<=M;i++)
if(d[i]<=xx)//如果是不大于xx长度的边
ins(x[i],y[i],1);//因为是求方案数,所以流量为1,表示一种方案
int ans=0;
while(bt_h()==true) ans=ans+findflow(st,2147483647);
return ans;
}
int main()
{
scanf("%d%d%d",&N,&M,&T);
st=1;ed=N;//起点和终点
int l=0,r=0;//二分查找的左右
for(int i=1;i<=M;i++)
{
scanf("%d%d%d",&x[i],&y[i],&d[i]);
if(d[i]>r) r=d[i];//求最长的边
}
int ans=0;
while(l<=r)//二分查找
{
int mid=(l+r)/2;
if(check(mid)>=T)
{
ans=mid;
r=mid-1;
}
else l=mid+1;
}
printf("%d\n",ans);
return 0;
}