poj 3680 Intervals

对于每个区间的端点进行保存,用set容器来保存点,任意相邻的点之间连(k,0)的线,对于输入的点连接(1,-w)的线,即离散化整个输入区间。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <set>
using namespace std;

struct node
{
	int u,v,cost,flow,next;
};

struct Line
{
	int start;
	int end;
	int w;
}line[405];

const int INF=1000000;
node edges[1000005];
const int maxn = 10005;
int head[maxn],e;
int pre[maxn],in[maxn],cost[maxn],flow[maxn];
int s,t;
queue<int> Q;

int g[105][105],n,m,K;

void add(int u,int v,int flow,int cost)
{
	edges[e].u=u;
	edges[e].v=v;
	edges[e].cost=cost;
	edges[e].flow=flow;
	edges[e].next=head[u];
	head[u]=e++;
}

void Add(int u,int v,int flow,int cost)
{
	add(u,v,flow,cost);
	add(v,u,0,-cost);
}

int SPFA(int s,int t)
{
	int i,u,v;
	memset(pre,-1,sizeof(pre));
	memset(flow,0,sizeof(flow));
	memset(in,0,sizeof(in));
	for(i=0;i<=t;i++) cost[i]=INF;
	while(!Q.empty()) Q.pop();
	Q.push(s);
	in[s]=1;
	flow[s]=INF;
	cost[s]=0;
	while(!Q.empty())
	{
		u=Q.front();
		Q.pop();
		in[u]=0;
		for(i=head[u];i!=-1;i=edges[i].next)
		{
			v=edges[i].v;
			if(edges[i].flow>0&&cost[v]>cost[u]+edges[i].cost)
			{
				cost[v]=cost[u]+edges[i].cost;
				pre[v]=i;
				flow[v]=min(flow[u],edges[i].flow);
				if(!in[v])
				{
					in[v]=1;
					Q.push(v);
				}
			}
		}
	}
	return flow[t];
}

int MCMF(int s,int t)
{
	int mincost=0,minflow,i;
	while((minflow=SPFA(s,t)))
	{
		for(i=pre[t];i!=-1;i=pre[edges[i].u])
		{
			mincost+=minflow*edges[i].cost;
			edges[i].flow-=minflow;
			edges[i^1].flow+=minflow;
		}
	}
	return mincost;
}

set<int> dot;

int main()
{
	int p;
	for(scanf("%d",&p);p;p--)
	{
		memset(head,-1,sizeof(head));
		int k,u,v,w;
		scanf("%d %d",&n,&k);
		dot.clear();
		for(int i = 1;i<=n;i++)
		{
			scanf("%d %d %d",&u,&v,&w);
			line[i].start = u;
			line[i].end = v;
			line[i].w = -w;
			dot.insert(u);
			dot.insert(v);
		}
		s = 0;
		for(int i = 1;i<dot.size();i++)
		{
			Add(i,i+1,k,0);
		}
		int tmp = 0;
		for(int i = 1;i<=n;i++)
		{
			int ss,ee;
			int j = 0;
			for(set<int>::iterator it = dot.begin();it!=dot.end();it++,j++)
			{
				if(*it==line[i].start)
				{
					ss = j+1;
				}
				if(*it==line[i].end)
				{
					ee = j+1;
				}
			}
			if(ss!=ee)
				Add(ss,ee,1,line[i].w);
			else
				tmp += line[i].w;
		}
		s = 0;
		Add(s,1,k,0);
		t = dot.size()+1;
		Add(dot.size(),t,k,0);
		int ans = MCMF(s,t);
		ans += tmp;
		printf("%d\n",-ans);
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值