loj 1407(2-sat + 枚举 + 输出一组可行解 )
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27115
思路:有一个trick要注意:当情况为 2 x y 时,可以推出当y留下时,x也必须留下。然后就是后面的k个限制关系,我们可以3^(k)次方枚举,一旦找到符合条件的就return 。然后就是反向建图,拓扑排序找可行解。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
#define MAXN 2222 int n,m,k;
struct Node{
int tag;
int num[];
}node[]; vector<vector<int> >g,gg,edge; int cnt,bcc_count;
int dfn[MAXN],low[MAXN],color[MAXN];
int degree[MAXN];
bool mark[MAXN];
stack<int>S; void Tarjan(int u)
{
low[u]=dfn[u]=++cnt;
mark[u]=true;
S.push(u);
for(int i=;i<edge[u].size();i++){
int v=edge[u][i];
if(dfn[v]==){
Tarjan(v);
low[u]=min(low[u],low[v]);
}else if(mark[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
int v;
bcc_count++;
do{
v=S.top();
S.pop();
mark[v]=false;
color[v]=bcc_count;
}while(u!=v);
}
} int opp[MAXN];
bool Check()
{
for(int i=;i<=n;i++){
if(color[i]==color[i+n])return false;
opp[color[i]]=color[i+n];
opp[color[i+n]]=color[i];
}
return true;
} bool Judge()
{
int kk=(int)pow(3.0,k);
for(int i=;i<kk;i++){
for(int j=;j<=*n;j++)edge[j]=g[j];
int j=i,_count=;
while(_count<k){
int id=j%;
int x=node[_count].num[id];
if(node[_count].tag==){
edge[x+n].push_back(x);
}else
edge[x].push_back(x+n);
_count++;
j/=;
}
cnt=bcc_count=;
memset(dfn,,sizeof(dfn));
memset(mark,false,sizeof(mark));
for(int j=;j<=*n;j++)if(dfn[j]==)Tarjan(j);
if(Check())return true;
}
return false;
} int vis[MAXN];
void TopSort()
{
queue<int>que;
for(int i=;i<=bcc_count;i++){
if(degree[i]==)que.push(i);
}
memset(vis,,sizeof(vis));
while(!que.empty()){
int u=que.front();
que.pop();
if(vis[u]==){
vis[u]=;
vis[opp[u]]=-;
}
for(int i=;i<gg[u].size();i++){
int v=gg[u][i];
if(--degree[v]==)que.push(v);
}
}
} vector<int>ans;
void Solve()
{
gg.clear();
gg.resize(*n+);
memset(degree,,sizeof(degree));
for(int u=;u<=*n;u++){
for(int i=;i<edge[u].size();i++){
int v=edge[u][i];
if(color[u]!=color[v]){
gg[color[v]].push_back(color[u]);
degree[color[u]]++;
}
}
}
TopSort();
ans.clear();
for(int i=;i<=n;i++)
if(vis[color[i]]==)ans.push_back(i);
printf("%d",(int)ans.size());
for(int i=;i<(int)ans.size();i++){
printf(" %d",ans[i]);
}
puts(".");
} int main()
{
int _case,x,y,z,tag,t=;
scanf("%d",&_case);
while(_case--){
scanf("%d%d%d",&n,&m,&k);
g.clear();
g.resize(*n+);
edge.clear();
edge.resize(*n+);
while(m--){
scanf("%d%d%d",&tag,&x,&y);
if(tag==)g[x+n].push_back(y),g[y+n].push_back(x);
else if(tag==)g[x+n].push_back(y+n),g[y].push_back(x);
else if(tag==)g[x].push_back(y+n),g[y].push_back(x+n);
else g[x].push_back(y+n),g[y].push_back(x+n),g[x+n].push_back(y),g[y+n].push_back(x);
}
for(int i=;i<k;i++){
scanf("%d%d%d%d",&node[i].tag,&node[i].num[],&node[i].num[],&node[i].num[]);
}
printf("Case %d: ",t++);
if(Judge()){
printf("Possible ");
Solve();
}else
puts("Impossible.");
}
return ;
}
loj 1407(2-sat + 枚举 + 输出一组可行解 )的更多相关文章
- poj 3683(2-sat+输出一组可行解)
题目链接:http://poj.org/problem?id=3683 思路:对于每个结婚仪式,只有在开始或结束时进行这两种选择,我们可以定义xi为真当且仅当在开始时进行.于是我们可以通过时间先后确定 ...
- loj 1251(2-sat + 输出一组可行解)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26961 思路:u表示留下,~u表示离开,同理v,对于+u,-v,我 ...
- poj 3683 2-sat问题,输出任意一组可行解
/* 2sat问题 输出任意一组可行解 */ #include<stdio.h> #include<string.h> #include<stdlib.h> #in ...
- SAM I AM UVA - 11419(最小顶点覆盖+输出一组解)
就是棋盘问题输出一组解 https://blog.csdn.net/llx523113241/article/details/47759745 http://www.matrix67.com/blog ...
- 2-sat 输出任意一组可行解&拓扑排序+缩点 poj3683
Priest John's Busiest Day Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8170 Accept ...
- loj 1154(最大流+枚举汇点)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26868 思路:拆点,容量为最多能跳的步数,然后设立一个超级源点,源 ...
- C语言实现输出一组数字中的所有奇数
/*第二题*/ #include<stdio.h> //输入186732468 //输出173 //输入12345677 //输出13577 main(){ ;//输入的数字,数字的长度 ...
- python应用-表格式输出一组数据
def main(): names=['关羽','张飞','赵云','马超','貂蝉'] subjects=['语文','数学','Python'] table=[[0 for _ in range( ...
- 【C语言】(数组方式)输出一组成绩中的最高分与最低分
两种不同方式获取最大值与最小值 代码1: #include <stdio.h> int main() { ], sum = , max, min; int i; printf(" ...
随机推荐
- html中table的画法及table和div的区别
最近项目中,根据客户的要求需要在页面上展示各种报表什么的,各种表格的都会出现.这里也将table的画法,做一下总结.办法虽笨但很实用.这也是从高人那里学来的,总之是屡试不爽啊.就以下面的表格为例. 若 ...
- Milking Cows
Milking Cows Three farmers rise at 5 am each morning and head for the barn to milk three cows. The f ...
- 不用插件直接同步wordpress文章日志到新浪微博
社会化媒体营销可以为网站带来流量,如果你的社会化媒体账号的粉丝技术够大的话!社会化媒体营销国内做得比较好的算新浪微博了.那么我们要怎样同步wordpress文章日志到新浪微博呢?当然你可以使用插件来实 ...
- CSS包含块containing block详解
“包含块(containing block)”,W3c中一个很重要的概念,今天带大家一起来好好研究下. 初步理解 在 CSS2.1 中,很多框的定位和尺寸的计算,都取决于一个矩形的边界,这个矩形,被称 ...
- Java中的构造函数和重载
一.Java中的构造函数 构造函数是对象被创建时初始化对象的成员方法,它具有和它所在的类完全一样的名字.构造函数只能有入口参数,没有返回类型,因为一个类的构造方法的返回类就是类本身.构造函数定义后,创 ...
- 忘记mysql root用户密码
今天帮一个售后的同事解决网盘无登录的问题,看了下后台日志,报错用密码root连接不上数据库,然后我就强行改了一下数据库密码,就OK了. (1)用root登录系统. (2)vim /etc/my.cnf ...
- 今天逛VC驿站 的收获
1.C++ 如何定义一个定长字符串, 若不足位数,就补字符串"0"? eg: CString str1 = “123”;不足20位,前面补“0”,实现效果为“00000000000 ...
- Minimum Depth of Binary Tree
二叉树的最小深度 采用递归的方式求左右结点的高度,注意判断一个结点是否是叶子结点(左右子树都不存大). int minDepth(TreeNode *root) { return minDepth(r ...
- python时间转换
#设a为字符串 import time a = "2011-09-28 10:00:00" #中间过程,一般都需要将字符串转化为时间数组 time.strptime(a,'%Y-% ...
- PHP+redis实现超迷你全文检索
2014年10月31日 11:45:39 情景: 我们平台有好多游戏, 运营的同事在查询某一款游戏的时候, 目前使用的是html的select下拉列表的展现形式, 运营的同事得一个个去找,然后选中,耗 ...