[2018雅礼省选集训3-30]path 平面图最短路最小割

12人阅读 评论(0) 收藏 举报
分类:

根据题意,题目给定的图是一个平面图。如果把1号点到不了的点和到不了n号点的点及所连边删掉,那么图就大概是有一条1n的链,然后还有一些边覆盖在上面,这样的话它的对偶图就大概是一棵树。
再考虑颜色限制怎么搞,假设x与其父亲的边在原图中代表边(u,v),那么xT割就表示不选u+1,...,v1这些点的颜色,于是对于每个颜色建一个点,然后xu+1,...,v1的颜色的点连容量正无穷的双向边。注意到xT割,那么其子树都在T割,因此x只需要向未被更底层边覆盖的点就可以了。
还有一个细节,注意到一个DAG的对偶图还是一个DAG,且对于任何一条ST的路径一定存在一条边(u,v)使得Su上的点在S割,vT上的点全在T割(就是不会S,T间隔,这样才对应原图一个合法路径),那么加上颜色限制后可能破坏这一点,所以在本题对偶图中每个点要向其父亲连一条容量为正无穷的边保证这一点。
代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#define N 1010
using namespace std;
const int inf=0x3f3f3f3f;
int n,m,c[N],z[N],S,T,dl[N<<1],ne[N<<1],st[N];
vector<int> gt[N],gr[N],tr[N];
bool bt[N],br[N];
struct node
{
    int x,y,w;
}e[N];
struct edge
{
    int t,c,f;
    edge *next,*rev;
}*con[N<<1];
void ins(int x,int y,int c)
{
    edge *p=new edge;p->t=y;p->c=c;p->f=0;p->next=con[x];con[x]=p;
    p=new edge;p->t=x;p->c=0;p->f=0;p->next=con[y];con[y]=p;
    con[x]->rev=con[y];con[y]->rev=con[x];
}
bool cmp(node p,node q)
{
    if(p.y-p.x==q.y-q.x) return p.x<q.x;
    return (p.y-p.x<q.y-q.x);   
}
bool bfs()
{
    memset(ne,0,sizeof(ne));
    ne[S]=1;dl[1]=S;bool re=0;
    for(int hd=1,tl=1,v=S;hd<=tl;re|=(v==T),v=dl[++hd])
        for(edge *p=con[v];p;p=p->next)
            if(p->c>p->f&&ne[p->t]==0) ne[p->t]=ne[v]+1,dl[++tl]=p->t;
    return re;
}
int dinic(int v,int flow)
{
    if(v==T) return flow;
    if(ne[v]==-1) return 0;
    int re=0;
    for(edge *p=con[v];p&&flow;p=p->next)
        if(p->c>p->f&&ne[p->t]==ne[v]+1)
        {
            int o=dinic(p->t,min(flow,p->c-p->f));
            p->f+=o;re+=o;
            p->rev->f-=o;flow-=o;
        }
    if(!re) ne[v]==-1;
    return re;  
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++)
        {scanf("%d",&c[i]);z[i]=c[i];}
    for(int i=1;i<=m;i++)
    {   
        scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
        gt[e[i].x].push_back(e[i].y);
        gr[e[i].y].push_back(e[i].x);
    }
    bt[0]=1;
    for(int i=0;i<=n;i++)
        if(bt[i])
            for(int j=0;j<gt[i].size();j++)
                bt[gt[i][j]]=1;
    br[n]=1;
    for(int i=n;i>=0;i--)
        if(br[i])
            for(int j=0;j<gr[i].size();j++)
                br[gr[i][j]]=1;
    if(!bt[n])
    {
        puts("-1");
        return 0;
    }
    int mm=m;m=0;
    for(int i=1;i<=mm;i++)
        if(bt[e[i].x]&&bt[e[i].y]&&br[e[i].x]&&br[e[i].y]) e[++m]=e[i];
    sort(e+1,e+m+1,cmp);
    S=0;T=n+m+1;
    for(int i=1;i<=m;i++)
    {
        int v=S;
        for(int j=i+1;j<=m;j++)
            if(v||(e[j].x<=e[i].x&&e[j].y>=e[i].y)) {v=j;break;}
        tr[v].push_back(i);
    }
    for(int i=0;i<=m;i++)
        for(int j=0;j<tr[i].size();j++)
            ins(i,tr[i][j],e[tr[i][j]].w),ins(tr[i][j],i,inf);
    for(int i=0;i<=m;i++)
    {
        int top=0;
        for(int j=0;j<tr[i].size();j++)
            st[++top]=e[tr[i][j]].x;
        sort(st+1,st+top+1);
        for(int j=2;j<=top;j++) 
            ins(i,c[st[j]]+m,inf),ins(c[st[j]]+m,i,inf);
    }
    for(int i=1;i<=m;i++)
        if(!tr[i].size())
        {
            ins(i,T,inf);
            for(int j=e[i].x+1;j<e[i].y;j++)
                ins(i,c[j]+m,inf),ins(c[j]+m,i,inf);
        }
    int ans=0;
    while(bfs()) ans+=dinic(S,inf);
    if(ans<inf) printf("%d",ans);
    else puts("-1");    
    return 0;
}
查看评论

三层开发基本概念介绍

 三层客户/服务器一:优点:灵活性和可扩展性。应用三层开发技术(分布式)的原因(参考书目: Delphi 5.x分布式多层应用系统篇)一:解决客户机/服务器结构的维护成本问题,改善客户机/服务器结构延...
  • coolriver
  • coolriver
  • 2002-11-17 11:51:00
  • 1209

雅礼集训1.4 序列

标签:迭代加深搜索,IDA* 题目 序列(sequence) 【题目描述】 给定一个1~n的排列x,每次你可以将x1~xi翻转。你需要求出将序列变为升序的最小操作次数。有多组数据。 【输入数...
  • qwerty1125
  • qwerty1125
  • 2018-01-05 17:43:05
  • 116

[2018雅礼集训1-12]小C的线段树 DP

题面 考虑当n>mn>m时答案为00,1≤nm≤1051\le nm \le 10^5,所以只用考虑n1052n的情况。 把一个区间看成一对括号,设fi,l,rf_{i,l,r}表示前ii个点,之...
  • DOFYPXY
  • DOFYPXY
  • 2018-01-17 22:14:21
  • 160

雅礼集训酱油记(2017-01-11~2017-01-23)

一句话:知道了自己有多弱。。。讲课: 第一天就完全懵逼了,毛爷爷的DP除了学过的听懂了一半,没学过的东西(Knuth、单调性、三分、凸包??)单词都认不到。。。酱油过去。 数据结构还算听懂得比较多...
  • can919
  • can919
  • 2017-01-24 21:59:00
  • 509

[2018雅礼集训1-10]Function 积性函数前缀和

题面 题目要我们求 ∑i=1n∑d|iμ(d)∗σ20(id)\sum_{i=1}^n\sum_{d|i}\mu(d)*\sigma_0^2(\frac{i}{d}) 设f(i)=∑d|iμ(d...
  • DOFYPXY
  • DOFYPXY
  • 2018-01-11 22:18:08
  • 165

[2018雅礼集训1-16]序列 爆搜+贪心

题面 首先问题转化为选取一个(Mi,Vi)(M_i,V_i)的集合,该集合必须满足若Mk|lcm{Mi}M_k|lcm\{M_i\},(Mk,Vk)(M_k,V_k)必须在集合中,最大化∑Vi\su...
  • DOFYPXY
  • DOFYPXY
  • 2018-01-18 20:51:14
  • 101

[2018雅礼集训1-20]B 分块

题面 考虑把序列分成N−−√\sqrt N块,记cnti,jcnt_{i,j}表示第ii块颜色jj的个数,设si,js_{i,j}为i,ji,j两块之间产生的贡献,通过cntcnt可以O(N−−√)...
  • DOFYPXY
  • DOFYPXY
  • 2018-01-20 20:34:31
  • 127

雅礼集训及WC2018划水记

雅礼集训1.30~2.3 noip考成250,没得去thuwc和pkuwc,和czy等去参加本来只有samjia和栋栋的集训队模拟。抱着被虐的心态去比赛。 第一天刚到比较困,比赛有点没精神,看到t...
  • ZLTJohn
  • ZLTJohn
  • 2018-02-12 22:25:15
  • 152

[2018雅礼集训1-16]方阵 stirling数反演

题面 如果只考虑行不相同,答案显然为(cM)N−(c^M)^\underline N。 再考虑列不相同的情况,把相同的列看成一个等价类,至多ii个等价类F(i)F(i)的方案为(ci)N−(c^i...
  • DOFYPXY
  • DOFYPXY
  • 2018-01-20 18:38:10
  • 135
    个人资料
    持之以恒
    等级:
    访问量: 2万+
    积分: 2428
    排名: 1万+
    最新评论