scu oj 4442 Party(2015年四川省acm程序设计竞赛)★ ★ ★

转载 2016年08月28日 18:18:50
转载自:http://blog.csdn.net/u012127882/article/details/47397919
题目意思:有n个青蛙喝茶,有些青蛙只能喝红茶,有些青蛙只能喝绿茶,有些青蛙红茶绿茶都可以喝。现在m对青蛙之间有矛盾,有矛盾的青蛙他们不能喝一样的茶,对于没每一只青蛙,可以给他w[i]金币,让他不喝茶,他就不会和任何青蛙矛盾了。最少需要给多少钱让他们之间没有矛盾存在。这题里面还有一个很重要的信息,我一开始没有看出来。这句话————“Luckily, frogs can be divided into 2 groups such that no two frogs in the same group dislike each other.”其实这句话很关键,它的意思就是这个矛盾关系图不存在奇环,是一个2分图论。 
 有了这个条件。我们现在考虑只能喝一种茶的青蛙,红和绿之间即使存在矛也没有影响,那么只用考虑红和红,绿和绿之间的矛盾关系。假设考虑2种都能喝的青蛙,那么红和红,绿和绿都是单独的求出最大点权独立集。由于是2分图,可以很容易求。现在考虑一只2种茶都可以喝的青蛙,这里是关键,我的解法是吧这个青蛙拆成2个点,一个点代表他和红茶,一个点代表他和绿茶,首先这2个点是不能同时存在,那么必然有边,然后如果这只青蛙和其他只和红茶的青蛙有矛盾关系,那么对应就是这个青蛙喝红点和那么青蛙喝红点不能同时存在,其他情况其实是类似的分析。这样拆点把矛盾关系图建立出来以后,实际上还是一个2分图,现在就是选出最大点权的点让这些点之间不存在矛盾关系。实际上就是点权最大独立集,转换成求点权最小覆盖的模型,就能很轻松的求解了。。。。。想这么久,果然是神建图。其实主要还是拆点。
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
using namespace std;
const int mmax  = 2010;
const int inf = 0x3fffffff;

struct node
{
    int flow;
    int en;
    int next;
}E[100*mmax];
int p[mmax];
int num;
void init()
{
    memset(p,-1,sizeof p);
    num=0;
}
void add(int st,int en,int flow)
{
    E[num].en=en;
    E[num].flow=flow;
    E[num].next=p[st];
    p[st]=num++;
    E[num].en=st;
    E[num].flow=0;
    E[num].next=p[en];
    p[en]=num++;
}

int d[mmax];
int cur[mmax];
bool vis[mmax];
bool bfs(int st,int en)
{
    memset(vis,0,sizeof vis);
    d[st]=0;
    vis[st]=1;
    queue<int>q;
    q.push(st);
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=p[x]; i+1; i=E[i].next)
        {
            int v=E[i].en;
            if(!vis[v]&&E[i].flow)
            {
                vis[v]=1;
                d[v]=d[x]+1;
                q.push(v);
            }
        }
    }
    return vis[en];
}
int dfs(int st,int en,int  flow)
{
    if(st==en||flow==0)
        return flow;
    int f=0,dd;
    for(int &i=cur[st]; i+1;i=E[i].next)
    {
        int v=E[i].en;
        if(d[st]+1==d[v]&&(dd=dfs(v,en,min(flow,E[i].flow)))>0)
        {
            E[i].flow-=dd;
            E[i^1].flow+=dd;
            flow-=dd;
            f+=dd;
            if(flow==0)
                break;
        }
    }
    return f;
}
int dinic(int st,int en,int n)
{
    int flow=0;
    while(bfs(st,en))
    {
        for(int i=0;i<=n;i++)
            cur[i]=p[i];
        flow+=dfs(st,en,inf);
    }
    return flow;
}

vector<int>e[mmax];
int fg[mmax];
int w[mmax];
void dfs(int u)
{
    int SZ=e[u].size();
    for(int i=0;i<SZ;i++)
    {
        int v=e[u][i];
        if(d[v]==-1)
        {
            d[v]=d[u]^1;
            dfs(v);
        }
    }
}
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=0;i<mmax;i++)
            e[i].clear();
        for(int i=1;i<=n;i++)
            scanf("%d",&w[i]);
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&fg[i]);
            if(fg[i]==3)
                sum+=w[i];
        }
        for(int i=0;i<m;i++)
        {
            int u,v;
            scanf("%d %d",&u,&v);
            e[u].push_back(v);
            e[v].push_back(u);
        }
        init();
        memset(d,-1,sizeof d);
        for(int i=1;i<=n;i++)
        {
            if(d[i]==-1)
            {
                d[i]=0;
                dfs(i);
            }
        }
        int st=0,en=2*n+1;
        for(int i=1;i<=n;i++)
        {
            if(d[i]==0)
            {
                if(fg[i]==1)
                    add(st,i,w[i]);
                if(fg[i]==2)
                    add(i,en,w[i]);
                if(fg[i]==3)
                {
                    add(st,i,w[i]);
                    add(i,i+n,inf);
                    add(i+n,en,w[i]);
                }
            }
            else
            {
                if(fg[i]==1)
                    add(i,en,w[i]);
                if(fg[i]==2)
                    add(st,i,w[i]);
                if(fg[i]==3)
                {
                    add(i,en,w[i]);
                    add(st,i+n,w[i]);
                    add(i+n,i,inf);
                }
            }
        }

        for(int u=1;u<=n;u++)
        {
            int Sz=e[u].size();
            for(int i=0;i<Sz;i++)
            {
                int v=e[u][i];
                if(d[u]==0 && d[v]==1)
                {
                    if( (fg[u]==fg[v]) &&   (fg[u]!=3) )
                    {
                        if(fg[u]==1)
                            add(u,v,inf);
                        else
                            add(v,u,inf);
                    }
                    else if(  (fg[u]==fg[v]) &&   (fg[u]==3)  )
                    {
                        add(u,v,inf);
                        add(v+n,u+n,inf);
                    }
                    else if(fg[u]==3 || fg[v]==3 )
                    {
                        if(fg[u]==3)
                        {
                            if(fg[v]==1)
                                add(u,v,inf);
                            else
                                add(v,u+n,inf);
                        }
                        if(fg[v]==3)
                        {
                            if(fg[u]==1)
                                add(u,v,inf);
                            else
                                add(v+n,u,inf);
                        }
                    }

                }
            }
        }
        printf("%d\n",dinic(st,en,en)-sum);
    }
    return 0;
}


scu oj 4442 Party(2015年四川省acm程序设计竞赛)(*)

Party n frogs are invited to a tea party. Frogs are conveniently numbered by 1,2,…,n. The te...
  • mosquito_zm
  • mosquito_zm
  • 2017年08月01日 09:35
  • 103

scu oj 4442 Party(2015年四川省acm程序设计竞赛)

Party n frogs are invited to a tea party. Frogs are conveniently numbered by 1,2,…,n. The tea party...
  • u012127882
  • u012127882
  • 2015年08月10日 14:29
  • 1322

2017 第十四届浙江acm省赛总结(退役???)

本人来自不知多少流的弱校, 三本独立学院(还是文科学校)。。。 摸爬打滚玩了三年,写篇总结篇吧,纪念一下即将逝去的acm之旅。 2017.4.22  算是第三次来到浙大紫金港吧,正直zju的校庆(...
  • h1021456873
  • h1021456873
  • 2017年04月26日 20:13
  • 1189

安徽大学第五届ACM/ICPC程序设计竞赛——学位的诱惑(又是水题)

这是安徽大学的程序设计大赛非常水的一道题  思路不需要说了  直接上代码吧  #include #include #include #include #include #...
  • qq_24751851
  • qq_24751851
  • 2015年05月20日 09:09
  • 1459

2015四川省赛 scu oj 4438 Censor

思路:此题主要考察对KMP算法的理解、其实删除的操作、可以用链表或者数组替换或者栈来实现、 #include #include #include #include #include ...
  • verticallimit
  • verticallimit
  • 2015年06月22日 00:26
  • 1077

2016四川省省赛总结

省赛过去接近八个月的时间了,然后想了一想,毕竟是大一参加的两场现场赛之一(还有一场是四川大学的邀请赛,理所当然的打铁了),所以还是补一发省赛总结吧,因为已经过去很久远的时间,所以照片什么的通通没有太多...
  • Nemaleswang
  • Nemaleswang
  • 2017年03月31日 22:22
  • 1258

河南省第六届ACM大学生程序设计竞赛 排行榜

2013 The Sixth Henan Province Programming Content. Asia Provincial-National Contests 2013 ...
  • liu_yutao
  • liu_yutao
  • 2013年05月13日 11:04
  • 2162

ACM-鸡兔同笼

描述 已知鸡和兔的总数量为n,总腿数为m。输入n和m,依次输出鸡和兔的数目,如果无解,则输出“No answer”(不要引号)。 输入第一行输入一个数据a,代表接下来共有几组数据,在接下来的(a ...
  • u012701023
  • u012701023
  • 2015年05月25日 23:22
  • 894

杭电ACM2015

题目的链接就不放上来了,自己去找 这一道题一上来之后,我的想法是: 需要先定义一个数组(然而我一上来定义成了一个浮点型的数组,后面定义a[n]时是按照整数走的。。。。。), 然先判断n\m,也就...
  • qq_38248287
  • qq_38248287
  • 2017年08月17日 14:56
  • 561

ACM2017四川省赛 E Longest Increasing Subsequence

题目链接:https://icpc-camp-cdn.b0.upaiyun.com/permanent/problems/sichuan-2017.pdf 题目大意:给出一组数字序列,求每次删掉一...
  • csdnzwj960331
  • csdnzwj960331
  • 2017年06月08日 19:24
  • 325
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:scu oj 4442 Party(2015年四川省acm程序设计竞赛)★ ★ ★
举报原因:
原因补充:

(最多只允许输入30个字)