poj3680 zkw费用流

25 篇文章 0 订阅
7 篇文章 0 订阅

真心给zkw大神跪了。。。

这个算是模板题,不过构图显然不是我想出来的。。。。

算是第一个费用流。。。

以后要多写点网络流啊。。


一开始我用vector存的边然后交上去竟然TLE!!!!!

这简直就是对vector党的鄙视啊。。。

然后没办法把vector注释掉换前向星了。。。

看来以后只能用前向星存图了。。。


#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<deque>
//#include<vector>
#define inf 100000007
#define MAX 55555
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define pb push_back

using namespace std;

int n,N,e=0,head[MAX];

void read(int &x)
{
	char c;
	int ret=0;
	while(c=getchar(),(c<'0'||c>'9')&&c!='-');
	if(c!='-')
	{
		ret=c-'0';
		while(c=getchar(),c>='0'&&c<='9')
			ret*=10,ret+=c-'0';
		x=ret;
		return;
	}
	else
	{
		while(c=getchar(),c>='0'&&c<='9')
			ret*=10,ret+=c-'0';
		x=-ret;
		return;
	}
}

struct ZKW
{
	struct Edge
	{
		int cost,cap,to,next,re;
	};

	//vector<Edge>edge;
	//vector<int>aim[MAX];

	Edge edge[MAX];

/*	void addedge(int From,int To,int Cap,int Cost)
	{
		edge.pb((Edge){From,To,Cap,Cost});
		edge.pb((Edge){To,From,0,-Cost});
		int size=edge.size();
		aim[From].pb(size-2);
		aim[To].pb(size-1);
	}*/

	void add_edge(int From,int To,int Cap,int Cost)
	{
		e++;
		edge[e].to=To;
		edge[e].cap=Cap;
		edge[e].cost=Cost;
		edge[e].re=e+1;
		edge[e].next=head[From];
		head[From]=e;
		e++;
		edge[e].to=From;
		edge[e].cap=0;
		edge[e].cost=-Cost;
		edge[e].re=e-1;
		edge[e].next=head[To];
		head[To]=e;
	}

	int s,t,cost,dis[MAX],done[MAX];
	int MinCost;

/*	void debug()
	{
		int w;
		for(int i=0;i<edge.size();i++)
			printf("%d %d\n",edge[i].from,edge[i].to);
	}*/

	void clear()
	{
		/*edge.clear();
		rep(i,0,n)
			aim[i].clear();*/
		memset(head,-1,sizeof(head));
		e=0;
		MinCost=cost=0;
		return;
	}

	bool modlabel()
	{
		memset(dis,63,sizeof(dis));
		dis[t]=0;
		deque<int>q;
		q.push_back(t);
		while(!q.empty())
		{
			int now=q.front(),tmp;
			q.pop_front();
			/*for(int i=0;i<aim[now].size();i++)
			{
				int w=aim[now][i];
				if(edge[w^1].cap&&(tmp=dis[now]-edge[w].cost)<dis[edge[w].to])
				{
					if((dis[edge[w].to]=tmp)<=dis[q.empty()?s:q.front()])
						q.push_front(edge[w].to);
					else
						q.push_back(edge[w].to);
				}
			}*/
			for(int i=head[now];i!=-1;i=edge[i].next)
				if(edge[edge[i].re].cap&&(tmp=dis[now]-edge[i].cost)<dis[edge[i].to])
				{
					if((dis[edge[i].to]=tmp)<=dis[q.empty()?s:q.front()])
						q.push_front(edge[i].to);
					else
						q.push_back(edge[i].to);
				}
		}

		rep(i,s,t)//?
			/*for(int j=0;j<aim[i].size();j++)
			{
				int w=aim[i][j];
				edge[w].cost+=dis[edge[w].to]-dis[edge[w].from];
			}*/
			for(int j=head[i];j!=-1;j=edge[j].next)
				edge[j].cost+=dis[edge[j].to]-dis[i];
		cost+=dis[s];
		return dis[s]<inf;
	}

	int aug(int x,int f)//?
	{
		if(x==t)    
		{
			MinCost+=f*cost;
			return f;
		}
		done[x]=1;
		int tmp=f;
		/*for(int i=0;i<aim[x].size();i++)
		{
			int now=aim[x][i];
			if(edge[now].cap&&!edge[now].cost&&!done[edge[now].to])
			{
				int delta=aug(edge[now].to,min(tmp,edge[now].cap));
				edge[now].cap-=delta;
				edge[now^1].cap+=delta;
				tmp-=delta;
				if(!tmp)
					return f;
			}
		}*/
		for(int i=head[x];i!=-1;i=edge[i].next)
			if(edge[i].cap&&!edge[i].cost&&!done[edge[i].to])
			{
				int delta=aug(edge[i].to,min(tmp,edge[i].cap));
				edge[i].cap-=delta;
				edge[edge[i].re].cap+=delta;
				tmp-=delta;
				if(!tmp)
					return f;
			}
		return f-tmp;
	}

	int work(int S,int T)
	{
		this->s=S;
		this->t=T;
		MinCost=0;
		while(modlabel())
		{
			do
			{
				memset(done,0,sizeof(done));
			}while(aug(s,inf));
		}
		return -MinCost;
	}
}wbysr;

int k,a[MAX],b[MAX],w[MAX],New[MAX],cnt,S,T;

inline void init()
{
	read(N),read(k);
	//scanf("%d%d",&N,&k);
	cnt=0;
	rep(i,1,N)
	{
		read(a[i]),read(b[i]),read(w[i]);
	//	scanf("%d%d%d",&a[i],&b[i],&w[i]);
		New[++cnt]=a[i];
		New[++cnt]=b[i];
	}
	sort(New+1,New+1+cnt);
	cnt=unique(New+1,New+1+cnt)-New-1;
}

int search(int x)
{
	int l=1,r=cnt;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(New[mid]==x)
			return mid;
		if(New[mid]<x)
			l=mid+1;
		else
			r=mid-1;
	}
	return -1;
}

inline void build()
{
	rep(i,1,N)
		wbysr.add_edge(search(a[i]),search(b[i]),1,-w[i]);
	n=cnt;
	rep(i,1,n-1)
		wbysr.add_edge(i,i+1,k,0);
	S=0;
	T=cnt+1;
	wbysr.add_edge(S,1,k,0);
	wbysr.add_edge(T-1,T,k,0);
	return;
}



int main()
{
	int time;
	scanf("%d",&time);
	while(time--)
	{
		getchar();
		wbysr.clear();
		init();
		build();
		printf("%d\n",wbysr.work(S,T));
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值