表示被这道题整得辛苦。
刚开始是P=40005写成了P=4005。wa了无数次之后才发现是这个问题。
然后是tle。因为刚开始因为最大流做题惯性有邻接表来存储。
一直tle好久。
然后再恍然大悟要用邻接矩阵。
思路其实挺简单:
有典型套路可做。这题很明显就是要“最短路”,但是这里的最短路是最长的权值最短,不是精确意义上的最短路。
然后再有一个约束就是要求出好几条不重叠的“最短路”,不重叠!套路是用二分+最大流来做,将边得权值都设为1。
如果重边则1+1=2,再重则3。
挺典型的。
#include<iostream>
#include<algorithm>
#define MIN(a,b) (a<b?a:b)
using namespace std;
const int N=205,P=40005;
const int inf=1<<30;
struct Edge
{
int u,v,w;
}edge[P];
int mat[N][N];
int que[N];
int visit[N];
int level[N];
int n,p,t;
bool cmp(const Edge& a,const Edge &b)
{
return a.w<b.w;
}
bool bfs()
{
memset(visit,0,sizeof(visit));
memset(level,0,sizeof(level));
int head=1,tail=1;
que[tail++]=0;
visit[0]=true;
level[0]=0;
while(head<tail)
{
int now=que[head++];
if(now==n+1)
return true;
for(int i=0;i<=n+1;i++)
{
if(!visit[i]&&mat[now][i]>0)
{
visit[i]=true;
que[tail++]=i;
level[i]=level[now]+1;
}
}
}
return false;
}
int dinic(int now,int sum)
{
if(now==n+1)
return sum;
int os=sum;
for(int i=0;i<=n+1&&sum>0;i++)
{
if(level[i]==level[now]+1&&mat[now][i]>0)
{
int tmp=dinic(i,MIN(sum,mat[now][i]));
mat[now][i]-=tmp;
mat[i][now]+=tmp;
sum-=tmp;
}
}
return os-sum;
}
bool make(int len)
{
memset(mat,0,sizeof(mat));
for(int i=1;i<=p&&edge[i].w<=len;i++)
{
mat[edge[i].u][edge[i].v]+=1;
mat[edge[i].v][edge[i].u]+=1;
}
mat[0][1]=t;
mat[n][n+1]=t;
int ans=0;
while(bfs())
{
ans+=dinic(0,inf);
}
if(ans>=t)
return true;
else
return false;
}
int main()
{
scanf("%d%d%d",&n,&p,&t);
int low=inf,high=0;
for(int i=1;i<=p;i++)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
if(low>edge[i].w)
low=edge[i].w;
if(high<edge[i].w)
high=edge[i].w;
}
sort(edge+1,edge+p+1,cmp);
low--;
high++;
while(low<high)
{
int mid=(low+high)/2;
if(make(mid))
{
high=mid;
}
else
{
low=mid+1;
}
}
printf("%d\n",low);
return 0;
}