UVA1391/LA3713 Astronauts
题意:有A、B、C3个任务分配给n个宇航员,其中每个宇航员恰好分配一个任务。假设n个宇航员的平均年龄为x,只有年龄大于x的才能领取A任务;只有年龄严格小于x的才能领取B任务,而任务C没有限制。有m对宇航员相互讨厌,因此不能分配同一任务。求出是否能找出符合的任务方案。(转自http://blog.csdn.net/u011345461/article/details/39779721)
题目看上去是ABC三个选择,实际上每个人只有两个选择。对于每对矛盾,如果两个人选择相同(即均为BC或均为AC),那么一个选C另一个必选B(A),另一个选C一个必选B(A),一个选B(A)另一个必选C,另一个选B(A)一个必选C;如果两个人选择不同(一个AC一个BC),那么一个选C另一个必选B,另一个选C一个必选A。
这题数据范围很大,好奇nm做法是怎么水过去的。。
正解是tarjan缩点,标记每个块的对立块,建立反图,对反图top排序,对于当前的块x,删除对立块和对立块在反图上的出边,并把当前快入队。最后看队列里没被删除的块即为答案块。把点扫一扫看看在不在答案块,在的话这个点的值代表选A(B)还是选C就是这个人的选择
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
template<class T>
inline void swap(T &a, T &b)
{
T tmp = a;a = b;b = tmp;
}
inline void read(int &x)
{
x = ;char ch = getchar(), c = ch;
while(ch < '' || ch > '') c = ch, ch = getchar();
while(ch <= '' && ch >= '') x = x * + ch - '', ch = getchar();
if(c == '-') x = -x;
}
const int INF = 0x3f3f3f3f;
const int MAXN = + ;
struct Edge
{
int u,v,nxt;
Edge(int _u, int _v, int _nxt){u = _u;v = _v;nxt = _nxt;}
Edge(){}
}edge1[MAXN << ], edge2[MAXN << ];
int head1[MAXN], head2[MAXN], vis[MAXN], tag[MAXN], rebelong[MAXN], del[MAXN], q[MAXN], he, ta, indeg[MAXN], cnt1, cnt2, n, m, belong[MAXN], group, b[MAXN], bb[MAXN], dfn[MAXN], stack[MAXN], top, low[MAXN], dfst, year[MAXN], x, tmp1, tmp2;
inline void insert1(int a, int b){edge1[++ cnt1] = Edge(a, b, head1[a]), head1[a] = cnt1;}
inline void insert2(int a, int b){edge2[++ cnt2] = Edge(a, b, head2[a]), head2[a] = cnt2;}
void dfs(int u)
{
b[u] = bb[u] = , dfn[u] = low[u] = ++ dfst, stack[++ top] = u;
for(int pos = head1[u];pos;pos = edge1[pos].nxt)
{
int v = edge1[pos].v;
if(!b[v]) dfs(v), low[u] = min(low[u], low[v]);
else if(bb[v]) low[u] = min(low[u], dfn[v]);
}
if(low[u] == dfn[u])
{
int now = -;++ group;
while(now != u) now = stack[top --], bb[now] = , belong[now] = group;
}
}
void rebuild()
{
memset(indeg, , sizeof(indeg)), memset(head2, , sizeof(head2));
for(int i = ;i <= cnt1;++ i)
if(belong[edge1[i].u] != belong[edge1[i].v])
insert2(belong[edge1[i].v], belong[edge1[i].u]), ++ indeg[belong[edge1[i].u]];
}
void tarjan()
{
memset(belong, , sizeof(belong)), memset(dfn, , sizeof(dfn)), memset(low, , sizeof(low)), group = , memset(b, , sizeof(b)), memset(bb, , sizeof(bb)), dfst = , top = , memset(rebelong, , sizeof(rebelong));
for(int i = ;i <= n;++ i) if(!b[i << ]) dfs(i << );
for(int i = ;i <= n;++ i) if(!b[i << | ]) dfs(i << | );
for(int i = ;i <= n;++ i) rebelong[belong[i << ]] = belong[i << | ], rebelong[belong[i << | ]] = belong[i << ];
rebuild();
}
void top_sort()
{
he = , ta = , memset(del, , sizeof(del));
for(int i = ;i <= group;++ i) if(!indeg[i]) q[ta ++] = i;
while(he < ta)
{
int now = q[he ++], renow = rebelong[now];
if(del[now]) continue; del[renow] = ;
for(int pos = head2[renow];pos;pos = edge2[pos].nxt)
{
int v = edge2[pos].v;
del[v] = ;
for(int poss = head2[v];poss;poss = edge2[poss].nxt) -- indeg[edge2[poss].v];
}
for(int pos = head2[now];pos;pos = edge2[pos].nxt)
{
int v = edge2[pos].v;
if(del[v]) continue;
-- indeg[v];
if(!indeg[v]) q[ta ++] = v;
}
}
}
int main()
{
while(scanf("%d %d", &n, &m) != EOF && n && m)
{
cnt1 = , memset(head1, , sizeof(head1)), x = ;
for(int i = ;i <= n;++ i) read(year[i]), x += year[i];
if(x % n == ) x = x / n;
else x = x / n + ;
for(int i = ;i <= n;++ i) year[i] = year[i] >= x; //year[i] = 1 表示选A或C year[i] = 0 表示选B或C
for(int i = ;i <= m;++ i)
{
read(tmp1), read(tmp2);
if(year[tmp1] == year[tmp2]) insert1(tmp1 << | , tmp2 << ), insert1(tmp2 << | , tmp1 << ), insert1(tmp1 << , tmp2 << | ), insert1(tmp2 << , tmp1 << | );
else insert1(tmp1 << | , tmp2 << ), insert1(tmp2 << | , tmp1 << );
}
tarjan();
int flag = ;
for(int i = ;i <= n;++ i) if(belong[i << | ] == belong[i << ]) flag = ;
if(flag)
{
printf("No solution.\n");
continue;
}
top_sort();
memset(vis, , sizeof(vis)), memset(tag, , sizeof(tag));
for(int i = ;i < ta;++ i) if(!del[q[i]]) vis[q[i]] = ;
for(int i = ;i <= n;++ i)
if(vis[belong[i << ]]) tag[i] = ;
else tag[i] = ;
for(int i = ;i <= n;++ i)
if(year[i] && !tag[i]) printf("A\n");
else if(!year[i] && !tag[i]) printf("B\n");
else printf("C\n");
}
return ;
}
UVA1391/LA3713
UVA1391/LA3713 Astronauts的更多相关文章
- 【UVALive - 3713】Astronauts (2-SAT)
题意: 有n个宇航员,按照年龄划分,年龄低于平均年龄的是年轻宇航员,而年龄大于等于平均年龄的是老练的宇航员. 现在要分配他们去A,B,C三个空间站,其中A站只有老练的宇航员才能去,而B站是只有年轻的才 ...
- UVA 3713 Astronauts
The Bandulu Space Agency (BSA) has plans for the following three space missions: • Mission A: Landin ...
- UVALive - 3713 - Astronauts(图论——2-SAT)
Problem UVALive - 3713 - Astronauts Time Limit: 3000 mSec Problem Description Input The input cont ...
- UVa 1391 Astronauts (2SAT)
题意:给出一些宇航员他们的年龄,x是他们的平均年龄,其中A任务只能给年龄大于等于x的人,B任务只能给小于x的人,C任务没有限制.再给出m对人,他们不能同任务.现在要你输出一组符合要求的任务安排. 思路 ...
- UVALive 3713 Astronauts (2-SAT,变形)
题意: 有A,B,C三种任务,每个人必获得1个任务,大于等于平均年龄的可以选择A和C,小于平均年龄的可以选择B和C.这些人有一些是互相讨厌的,必须不能执行同任务,问能否安排他们工作?若行,输出任意一组 ...
- UVALive - 3713 Astronauts
给定n个宇航员的年龄,平均年龄为 ave,根据下列要求分配任务: B任务只能分配给年龄<ave的宇航员: A任务只能分配给年龄>=ave的宇航员: C任务可以任意分配. 给定m组互相憎恨的 ...
- uva 1391 Astronauts(2-SAT)
/*翻译好题意 n个变量 不超过m*2句话*/ #include<iostream> #include<cstdio> #include<cstring> #inc ...
- UVAlive3713 Astronauts(2-SAT)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18511 [思路] 2-SAT. 设分得A或B类任务为1 C类任务为 ...
- uva1391 2-SAT 问题
题意在大白书上. 有3 种工作 abc 大于等于平均年龄的可以去做a c 工作, 小于平均年龄的可以去做 bc , 同样转化为2 -sat 去做, 因为对于每个人也只有2 种情况可以作为选择 #inc ...
随机推荐
- ReadyAPI创建功能测试的多种方法
原文:ReadyAPI创建功能测试的多种方法 声明:如果你想转载,请标明本篇博客的链接,请多多尊重原创,谢谢! 本篇使用的 ReadyAPI版本是2.5.0 在ReadyAPI中有多种方法可以创建功能 ...
- Derby的安装与使用
Derby数据库是一个纯用Java实现的内存数据库,属于Apache的一个开源项目.由于是用Java实现的,所以可以在任何平台上运行:另外一个特点是体积小,免安装,只需要几个小jar包就可以运行了. ...
- 基于windows消息的响应USB插入或取出
导语:当有设备进入windows时,系统会向所有的应用层发送WM_DEVICECHANGE消息.进一步根据相应的事件判断设备. LRESULT CALLBACK WndProc(HWND hWnd, ...
- 模块介绍/time/os...
本节大纲: 模块介绍 time &datetime模块 random os sys shutil json & picle shelve xml处理 yaml处理 configpars ...
- 编译安装redis-3.2.9(latest stable version)
What is the Redis? Redis is an open source (BSD licensed), in-memory data structure store, used as a ...
- leetcode-154-寻找旋转排序数组中的最小值
题目描述: 方法一: class Solution: def findMin(self, nums: List[int]) -> int: left, right = 0, len(nums) ...
- 【JZOJ3362】【BZOJ3758】数数
description 神犇最近闲来无事,于是就思考哲学,研究数字之美.在神犇看来,如果一个数的各位能够被分成两个集合,而且这两个集合里的数的和相等,那么这个数就是优美的(具体原因就只有神犇才知道了) ...
- Spring Boot 配置 Security 密码加密
依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spri ...
- LUOGU P2580 于是他错误的点名开始了(trie树)
传送门 解题思路 trie树模板
- SQL中的long text
SQL中的long text 问题: 解决方法: SELECT CONVERT(VARCHAR(5000),参考文献) AS 参考文献 FROM tpi20160503 出现原因: