题意:有N个地点,FJ 想从1走到N 每条边只能走一遍 走T次 求在满足条件下,最大的边最小。
思路:这题跟 poj 3228 Gold Transportation(二分+最大流) 这题差不多,就是用二分求出满足条件下的最小边权 EK超时,此题用sap做的
//3212K
797MS
#include <stdio.h>
#include <string.h>
#define VM 210
#define EM 160010
//建边重复1遍,所以是4*40000
int head[VM],oldhead[VM],dep[VM],gap[VM],cur[VM],pre[VM];
int e1,e,n,p,t,src,des;
struct E
{
int to,cap,nxt;
}edge[EM],oldedge[EM];
void addedge1 (int cu,int cv,int cw)
{
oldedge[e1].to = cv;
oldedge[e1].cap = cw;
oldedge[e1].nxt = oldhead[cu];
oldhead[cu] = e1 ++;
}
void addedge (int cu,int cv,int cw)
{
edge[e].to = cv;
edge[e].cap = cw;
edge[e].nxt = head[cu];
head[cu] = e ++;
}
void Build (int num) //构建一新的图
{
memset (head,-1,sizeof(head));
e = 0;
for (int u = 1;u <= n;u ++)
for (int i = oldhead[u];i != -1;i = oldedge[i].nxt)
{
int v = oldedge[i].to;
if (oldedge[i].cap <= num)
{
addedge (u,v,1);
//边权为1就可以了
addedge (v,u,1);
}
}
}
int Sap ()
//sap算法,不解释
{
memset (dep,0,sizeof(dep));
memset (gap,0,sizeof(gap));
memcpy (cur,head,sizeof(head));
int u = pre[src] = src;
int res = 0;
gap[0] = n;
while (dep[src] < n)
{
loop:
for (int &i = cur[u];i != -1;i = edge[i].nxt)
{
int v = edge[i].to;
if (edge[i].cap && dep[u] == dep[v] + 1)
{
pre[v] = u;
u = v;
if (v == des)
{
res ++; //记录走了多少次
for (u = pre[u];v != src;v = u,u = pre[u])
{
edge[cur[u]].cap -= 1;
edge[cur[u]^1].cap += 1;
}
}
goto loop;
}
}
int mindep = n;
for (int i = head[u];i != -1;i = edge[i].nxt)
{
int v = edge[i].to;
if (edge[i].cap && mindep > dep[v])
{
cur[u] = i;
mindep = dep[v];
}
}
if ((--gap[dep[u]]) == 0)
break;
dep[u] = mindep + 1;
gap[dep[u]] ++;
u = pre[u];
}
return res;
}
int main ()
{
int u,v,w;
while (~scanf ("%d%d%d",&n,&p,&t))
{
memset (oldhead,-1,sizeof(oldhead));
e1 = 0;
src = 1,des = n;
while (p --)
{
scanf ("%d%d%d",&u,&v,&w);
addedge1 (u,v,w);
addedge1 (v,u,w);
}
int l = 0,r = 1000000;
int ans = 0;
while (l <= r)
{
int mid = (l + r)>>1;
Build(mid);
int sum = Sap ();
sum /= 2;
//这里要注意 因为建边是重复了,所以得除2 比如说:1到2有边 因为是无向图
if (sum >= t)
//当遍历到1结点时会建1-->2和2-->1,遍历到2时,会建2-->1和1-->2 所以重复
{
ans = mid;
r = mid - 1;
}
else
l = mid + 1;
}
printf ("%d\n",ans);
}
return 0;
}
思路:这题跟 poj 3228 Gold Transportation(二分+最大流) 这题差不多,就是用二分求出满足条件下的最小边权 EK超时,此题用sap做的
//3212K
#include <stdio.h>
#include <string.h>
#define VM 210
#define EM 160010
int head[VM],oldhead[VM],dep[VM],gap[VM],cur[VM],pre[VM];
int e1,e,n,p,t,src,des;
struct E
{
}edge[EM],oldedge[EM];
void addedge1 (int cu,int cv,int cw)
{
}
void addedge (int cu,int cv,int cw)
{
}
void Build (int num)
{
}
int Sap ()
{
}
int main ()
{
}