POJ-2455-Secret Milking Machine

378 篇文章 0 订阅

这个题TLE了我N次,想不到Dinic会被卡,后来看了下别人写的代码,发现DFS中有不同之处,改了下结果就奇迹班的200多ms过了,看来以后改进下自己的写法了

这个题不太难吧,图建立不难,可能只是卡时间吧,题目大意是说求1到n点的t条不同路径的最大值的最小值

最大最小值问题用二分法做

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=410;
const int maxm=40100;
const int maxe=80100;
const int inf=1<<29;
int n,p,t,e,head[maxn],pnt[maxe],nxt[maxe],cost[maxe],level[maxn],q[maxn];
int l,r;
struct Edge
{
    int from;
    int to;
    int cost;
}E[maxm];
void AddEdge(int u,int v,int c)
{
    pnt[e]=v;nxt[e]=head[u];cost[e]=c;head[u]=e++;
    pnt[e]=u;nxt[e]=head[v];cost[e]=c;head[v]=e++;
}
void Build(int val)
{
    e=0;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=p;i++)
	if(E[i].cost<=val)
	    AddEdge(E[i].from,E[i].to,1);
}
bool BFS(int st)
{
    memset(level,0,sizeof(level));
    int pre=0,last=1;
    level[st]=1;
    q[pre]=st;
    while(pre<last)
    {
	if(q[pre]==n)
	    return true;
	for(int i=head[q[pre]];i!=-1;i=nxt[i])
	    if(cost[i]&&!level[pnt[i]])
	    {
		level[pnt[i]]=level[q[pre]]+1;
		q[last++]=pnt[i];
	    }
	pre++;
    }
    return level[n];
}
int DFS(int u,int sum)
{
    if(u==n)
	return sum;
    for(int i=head[u],s;i!=-1;i=nxt[i])
	if(level[pnt[i]]==level[u]+1&&cost[i]&&(s=DFS(pnt[i],min(sum,cost[i]))))
	{
	    cost[i]-=s;
	    cost[i^1]+=s;
	    return s;
	}
    level[u]=0;
    return 0;
}
int Go()
{
    int ans=0;
    while(l<=r)
    {
	int mid=(l+r)>>1;
	Build(mid);
	int sum=0;
	while(BFS(1))
	    while(1)
	    {
		int val=DFS(1,inf);
		if(!val)
		    break;
		sum+=val;
	    }
	if(sum>=t)
	{
	    ans=mid;
	    r=mid-1;
	}
	else
	    l=mid+1;
    }
    return ans;
}
int main()
{
    while(scanf("%d%d%d",&n,&p,&t)!=EOF)
    {
	l=inf,r=0;
	for(int i=1;i<=p;i++)
	{
	    scanf("%d%d%d",&E[i].from,&E[i].to,&E[i].cost);
	    l=min(l,E[i].cost);
	    r=max(r,E[i].cost);
	}
	printf("%d\n",Go());
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值