zoukankan      html  css  js  c++  java
  • 洛谷P3358 最长k可重区间集问题

    题目大意:

    在一段区间中存在一些线段

    要求从中选出一些线段,使得线段每个点被线段覆盖次数不超过(k)次,且线段长度最长

    最大费用最大流

    我们可以由(S)向区间的起点连边,终点向(T)连边,容量为(k),费用为(0),保证了每个点被经过不超过(k)

    每个点向下一个点连边,容量(k),花费(0)

    每个区间左断点向右端点连边,容量(1),花费为区间长度

    #include<bits/stdc++.h>
    using namespace std;
    inline int read()
    {
    	int x=0,f=1;
    	char ch;
    	for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    	if(ch=='-') f=0,ch=getchar();
    	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    	return f?x:-x;
    }
    const int inf=0x3f3f3f3f;
    int n,k,ret,st,ed;
    int tx[1010],ty[1010],s[1010];
    int head[100010],cnt=1;
    struct point
    {
    	int nxt,to,c,val;
    }a[200010];
    inline void add(int x,int y,int c,int val)
    {
    	a[++cnt].nxt=head[x];
    	a[cnt].to=y;
    	a[cnt].c=c;
    	a[cnt].val=val;
    	head[x]=cnt;
    }
    inline void adds(int x,int y,int c,int val)
    {
    	add(x,y,c,val);add(y,x,0,-val);
    }
    queue<int> q;
    int dis[100010],c[100010],pre[100010],eg[100010];
    bool vis[100010];
    inline bool spfa()
    {
    	memset(c,0x3f,sizeof(c));
    	memset(dis,-0x3f,sizeof(dis));dis[st]=0;
    	memset(vis,0,sizeof(vis));vis[st]=1;
    	q.push(st);pre[ed]=0;
    	while(!q.empty())
    	{
    		int now=q.front();
    		q.pop();
    		vis[now]=0;
    		for(int i=head[now];i;i=a[i].nxt)
    		{
    			int t=a[i].to;
    			if(a[i].c&&dis[t]<dis[now]+a[i].val)
    			{
    				pre[t]=now;
    				eg[t]=i;
    				dis[t]=dis[now]+a[i].val;
    				c[t]=min(c[now],a[i].c);
    				if(!vis[t])
    				{
    					vis[t]=1;
    					q.push(t);
    				}
    			}
    		}
    	}
    	return pre[ed];
    }
    inline int dinic()
    {
    	while(spfa())
    	{
    		ret+=dis[ed]*c[ed];
    		int now=ed;
    		while(now^st)
    		{
    			a[eg[now]].c-=c[ed];
    			a[eg[now]^1].c+=c[ed];
    			now=pre[now];
    		}
    	}
    	return ret;
    }
    signed main()
    {
    	n=read(),k=read();
    	for(int i=1;i<=n;++i)
    	{
    		tx[i]=read(),ty[i]=read();
    		s[++s[0]]=tx[i],s[++s[0]]=ty[i];
    	}
    	sort(s+1,s+s[0]+1);
    	s[0]=unique(s+1,s+s[0]+1)-s-1;//离散
    	st=s[0]+1,ed=s[0]+2;
    	for(int i=1;i<s[0];++i) adds(i,i+1,k,0);//每个点向右边连0边
    	adds(st,1,k,0);adds(s[0],ed,k,0);//起点终点,k个流限制每个点走k次
    	for(int x,y,i=1;i<=n;++i)
    	{
    		x=lower_bound(s+1,s+s[0]+1,tx[i])-s;
    		y=lower_bound(s+1,s+s[0]+1,ty[i])-s;
    		adds(x,y,1,ty[i]-tx[i]);//走线段
    	}
    	printf("%d
    ",dinic());//最大费用最大流
    return 0;
    }
    
  • 相关阅读:
    python的xpinyin模块:汉字转拼音
    中文报错SyntaxError: Non-UTF-8 code starting with 'xe6' in file
    "底层逻辑”是什么意思?
    【Golang】关于Go中logrus的用法
    【Golang】 关于Go语言中的锁
    【Golang】Go 通过结构(struct) 实现接口(interface)
    【Golang】Go语言之log的使用
    【Golang】Go中时间(time)的用法以及gorm处理时间戳
    【Golang】Go中三个点(...)用法
    一文彻底掌握Apache Hudi异步Clustering部署
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12095799.html
Copyright © 2011-2022 走看看