题目
题解
–这道题是啥来着,反正不是图论题就好了(23333)
我们发现最后的答案肯定是某条边的左端点,和某条边的右端点
所以我们直接枚举一下左端点的答案,再利用贪心原则,将r从大到小排序后,满足l<=答案(就是可以走过的边),依次加入并查集中,每次加入后,判断1和n的连通性,如果连通,就知道了一组答案了,r就是加入的边中的最小值
最后取最大值就行(记住要路径压缩)
是O(m^2)的,没有问题,跑的很快
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=1005;
int n,m;
struct hehe{
int u,v;
int l,r;
}edge[MAXN*3];
int e,a[MAXN*3],b[MAXN*3];
int ansl,ansr;
int fa[MAXN];
bool can(int a,int b,int l,int r){
if(a<=l)
return b>=l;
else
return r>=a;
}
bool Comp(const int &a,const int &b){
if(edge[a].r==edge[b].r)
return edge[a].l<edge[b].l;
return edge[a].r>edge[b].r;
}
int Get(int x){
if(x==fa[x])
return x;
return fa[x]=Get(fa[x]);
}
int main(){
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v,l,r;
scanf("%d%d%d%d",&u,&v,&l,&r);
e++;
edge[e].u=u;
edge[e].v=v;
edge[e].l=l;
edge[e].r=r;
a[e]=e;
}
sort(a+1,a+1+e,Comp);
for(int i=1;i<=e;i++){
int l=edge[i].l,r=edge[i].r;
for(int j=1;j<=n;j++)
fa[j]=j;
for(int j=1;j<=e;j++){
if(edge[a[j]].l<=l){
int u=edge[a[j]].u,v=edge[a[j]].v;
int fu=Get(u),fv=Get(v);
if(fu!=fv){
fa[fu]=fv;
if(r>edge[a[j]].r)
r=edge[a[j]].r;
}
if(Get(1)==Get(n)){
if(ansr-ansl+1<r-l+1){
ansr=r;
ansl=l;
}
break;
}
}
}
}
if(ansr&&ansl){
printf("%d\n",ansr-ansl+1);
for(int i=ansl;i<=ansr;i++)
printf("%d ",i);
}
else
cout<<0;
return 0;
}