UVALive 3713 Astronauts

题意:

有n个宇航员  他们需要完成A、B、C三种任务  年龄>=平均年龄的人可以做A和C  年龄<平均年龄的能做B和C  且宇航员之间有讨厌关系不能一起做任务  要求给出一种分配方案

思路:

一类人有2种选择而且必须选1个  因此想到2-sat  根据年龄和讨厌关系来建边  之后先做可行性判断  确定可以后  求出任意一组可行解  不需要字典序最小

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 200010

struct edge
{
    int u,v,next;
}ed[N*4];
int n,m,tot,top,cnt,idx;
int dfn[N],low[N],st[N],instack[N],belong[N],head[N],f[N],col[N],in[N],qu[N],opt[N];

void tarjan(int u)
{
    int i,v;
    dfn[u]=low[u]=++idx;
    instack[u]=1;
    st[++top]=u;
    for(i=head[u];~i;i=ed[i].next)
    {
        v=ed[i].v;
        if(dfn[v]==-1)
        {
            tarjan(v);
			low[u]=min(low[u],low[v]);
        }
        else if(instack[v]&&dfn[v]<low[u]) low[u]=dfn[v];
    }
    if(dfn[u]==low[u])
    {
        cnt++;
        do
        {
            v=st[top--];
            instack[v]=0;
            belong[v]=cnt;
        }while(u!=v);
    }
}

void init()
{
    tot=top=cnt=idx=0;
    for(int i=0;i<n;i++)
    {
        head[i]=-1;
        dfn[i]=-1;
        col[i]=0;
        in[i]=0;
    }
}

void add(int u,int v)
{
    ed[tot].u=u;
    ed[tot].v=v;
    ed[tot].next=head[u];
    head[u]=tot++;
}

bool can()
{
    int i,u,v;
    init();
    for(i=0;i<m;i++)
    {
        scanf("%d%d",&u,&v);
        u--;
        v--;
        u<<=1;
        v<<=1;
        if(f[u]==f[v])
        {
            add(u,v^1);
            add(v,u^1);
        }
        add(u^1,v);
        add(v^1,u);
    }
    for(i=0;i<n;i++)
    {
        if(dfn[i]==-1) tarjan(i);
    }
    for(i=0;i<n;i+=2)
    {
        if(belong[i]==belong[i^1]) return false;
    }
    return true;
}

void solve()
{
    int i,u,v,s=tot,l,r;
    for(i=1;i<=cnt;i++) head[i]=-1;
    tot=0;
    for(i=0;i<s;i++)
    {
        u=belong[ed[i].u];
        v=belong[ed[i].v];
        if(u!=v)
        {
            add(v,u);
            in[u]++;
        }
    }
    for(i=0;i<n;i++) opt[belong[i]]=belong[i^1];
    l=r=0;
    for(i=1;i<=cnt;i++)
    {
        if(!in[i]) qu[r++]=i;
    }
    while(l<r)
    {
        u=qu[l++];
        if(!col[u])
        {
            col[u]=1;
            col[opt[u]]=2;
        }
        for(i=head[u];~i;i=ed[i].next)
        {
            v=ed[i].v;
            in[v]--;
            if(!in[v]) qu[r++]=v;
        }
    }
}

int main()
{
    int i,sum;
    double tmp;
    while(~scanf("%d%d",&n,&m))
    {
        if(!n&&!m) break;
        sum=0;
        n<<=1;
        for(i=0;i<n;i+=2)
        {
            scanf("%d",&f[i]);
            sum+=f[i];
        }
        tmp=(double)(sum)/(n>>1);
        for(i=0;i<n;i+=2)
        {
            if(fabs(tmp-f[i])<1e-8||f[i]>tmp) f[i]=1;
            else f[i]=2;
            f[i+1]=3;
        }
        if(can())
        {
            solve();
            for(i=0;i<n;i+=2)
            {
                if(col[belong[i]]==1)
                {
                    if(f[i]==1) puts("A");
                    else puts("B");
                }
                else puts("C");
            }
        }
        else puts("No solution.");
    }
    return 0;
}
时间: 2024-10-04 18:02:24

UVALive 3713 Astronauts的相关文章

UVALive 3713 Astronauts (2-SAT,变形)

题意:有A,B,C三种任务,每个人必获得1个任务,大于等于平均年龄的可以选择A和C,小于平均年龄的可以选择B和C.这些人有一些是互相讨厌的,必须不能执行同任务,问能否安排他们工作?若行,输出任意一组解. 思路: 依然是 2-SAT,只不过换了个样子,建图时不同而已.这里每个人依然有2人选择,也有冲突的出现,问题在如何找出冲突. 首先,无论是哪两人,只要互相讨厌,去抢C,必定冲突.其次,如果是同龄人(同大于等于,或同小于),那么抢他们那个年龄段的任务也会冲突.所以共计2种,每种2条边,即我选的时候

UVALive - 3713 Astronauts(2-SAT)

题目大意:有A,B,C 3个任务要飞配给n个宇航员,现给出n个宇航员的年龄和每种任务的执行要求. A任务只有年龄大于等于平均年龄的宇航员才可以执行 B任务只有年龄小于平均年龄的宇航员才可以执行 C任务任何宇航员都可以执行 现在有M对讨厌关系,互相讨厌的宇航员不能执行同一种任务,现要求找出一个满足上述所有要求的任务分配方案 解题思路:年龄大于等于平均年龄的宇航员只能执行A任务或者C任务,假设执行A任务为true 同理,年龄小于平均年龄的宇航员只能执行B任务或者C任务,假设执行B任务为true 如果

UVA Live 3713 Astronauts

用布尔变量表示状态,把限制条件转化为XνY的形式以后跑2SAT,根据变量取值输出方案. #include<bits/stdc++.h> using namespace std; const int maxn = 1e5+5; #define PB push_back bool vis[maxn*2]; vector<int> G[maxn*2]; int N,S[maxn*2],top; void initGraph(int n) { N = n*2; for(int i = 0;

LA 3713 Astronauts

给个题目链接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1714 显然每个人只有两种选择:C或者A/B.而且后一种只和这个人的年龄有关. 这就是一个很显然的2-SAT模型了,显然有矛盾的不能都选C,如果两个人的年龄段还一样,那就更悲剧了,也不能同时选A/B. #include<iostream> #incl

{TwoSAT}

今天学习图论的时候,碰到了2sat问题 虽然不是很难理解,感觉很精妙 ▄█?█● 用的LRJ白书上的模板. 套路如下:  2 - SAT就是2判定性问题,是一种特殊的逻辑判定问题. 选择的置为1,未选的置为0 对于2SAT,每组矛盾都会有四种情况(2*2),题目会限制一种不成立,我们要做的就是找出这一种,用逻辑连接词表示出来,然后取反,加边即可. 具体过程白书上p324有讲,这里就不说了. 下面附三道题,做做就知道套路了 Party HDU - 3062 1 #include <bits/std

Uva 1391 (LA 3713) Astronauts (2-SAT问题)

今天学了2-SAT问题,就找了这道例题,敲了一下,还好过了. 2-SAT问题应该是把一些布尔变量之间的逻辑关系反映到一个无向图(有时可能是有向图)上来.通过推导的形式在这个有向图里面补边.再通过确定一些变量的值,使所有的变量都能符合题意中逻辑关系.补边方式 即如果Xi = true && Xj = false 不符合题意,那么如果Xi == true ,那么就在 Xi = true 和 Xj = true之间连一条边, 使得当Xi = true 时能马上确定 Xj = true. 在实际操

LA 3713

The Bandulu Space Agency (BSA) has plans for the following three space missions: Mission A: Landing on Ganymede, the largest moon of Jupiter. Mission B: Landing on Callisto, the second largest moon of Jupiter. Mission C: Landing on Titan, the largest

UVALive 4848 Tour Belt

F - Tour Belt Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVALive 4848 Description Korea has many tourist attractions. One of them is an archipelago (Dadohae in Korean), a cluster of small islands sca

UVALive 6467 Strahler Order 拓扑排序

这题是今天下午BNU SUMMER TRAINING的C题 是队友给的解题思路,用拓扑排序然后就可以了 最后是3A 其中两次RE竟然是因为: scanf("%d",mm); ORZ 以后能用CIN还是CIN吧 QAQ 贴代码了: 1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <math.h> 5 #include <iostre