light oj 1251 - Forming the Council (2-SAT + 输出任意解)
2015-10-10 17:29
323 查看
1251 - Forming the Council
In a city there are n voters, and m people formed the Govt. council. The council members are numbered from 1 to m. Now everyone is complaining that the council is biased. So, they made a
plan. The plan is that the voters are given a chance to vote again to form the new council. A vote will be like ±i ±j. '+' means the voter wants that member to be in the council, '-' means the voter doesn't
want the member to be in the council. For example, there are 4 voters, they voted like
+1 -3 the voter wants member 1 to be kept in the council or member 3 to be thrown out
+2 +3 the voter wants member 2 to be kept in the council or member 3 to be kept in the council
-1 -2 the voter wants member 1 to be thrown out or member 2 to be thrown out
-4 +1 the voter wants member 4 to be thrown out or member 1 to be kept in the council
A voter will be satisfied if at least one of his wishes becomes true. Now your task is to form the council such that all the voters are happy.
Each case starts with a line containing two integers n (1 ≤ n ≤ 20000) and m (1 ≤ m ≤ 8000). Each of the next n lines contains a vote in the form ±i ±j (1 ≤ i, j ≤ m).
in ascending order. And print a single space between two numbers. There can be many solutions. Any valid one will do.
题意:n个公民m个议员,n个公民对m个公民进行投票,+i表示希望i号议员留下,-i希望i号议员离开,问是否存在一组解满足全部的n个投票,有的话输出任意一组解。
思路:每个公民的投票a||b建图,!a->b , !b->a。
代码:
#include <iostream>
#include <functional>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b) for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b) for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v) memset ((t) , v, sizeof(t))
#define sf(n) scanf("%d", &n)
#define sff(a,b) scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf printf
#define DBG pf("Hi\n")
typedef long long ll;
using namespace std;
#define INF 0x3f3f3f3f
#define mod 1000000009
const int maxn = 1005;
const int MAXN = 20005;
const int MAXM = 200010;
const int N = 1005;
struct Edge
{
int to,next;
}edge[MAXM];
int head[MAXN],tot;
void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
int n,m;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
int Index,scc,top;
bool Instack[MAXN];
void Tarjan(int u)
{
int v;
Low[u]=DFN[u]=++Index;
Stack[top++]=u;
Instack[u]=true;
for (int i=head[u];~i;i=edge[i].next)
{
v=edge[i].to;
if (!DFN[v])
{
Tarjan(v);
if (Low[u]>Low[v]) Low[u]=Low[v];
}
else if (Instack[v]&&Low[u]>DFN[v]) Low[u]=DFN[v];
}
if (Low[u]==DFN[u])
{
scc++;
do{
v=Stack[--top];
Instack[v]=false;
Belong[v]=scc;
}while (v!=u);
}
}
bool solve(int n)
{
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
Index=scc=top=0;
for (int i=0;i<n;i++)
if (!DFN[i]) Tarjan(i);
for (int i=0;i<n;i+=2)
if (Belong[i]==Belong[i^1])
return false;
return true;
}
queue<int>q;
vector<vector<int> >dag;
int color[MAXN];
int indeg[MAXN];
int cf[MAXN];
void topsort(int n)
{
dag.assign(scc+1,vector<int>());
memset(indeg,0,sizeof(indeg));
memset(color,0,sizeof(color));
for (int u=0;u<n;u++)
{
for (int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].to;
if (Belong[u]!=Belong[v])
{
dag[Belong[v]].push_back(Belong[u]);
indeg[Belong[u]]++;
}
}
}
for (int i=0;i<n;i+=2)
{
cf[Belong[i]]=Belong[i^1];
cf[Belong[i^1]]=Belong[i];
}
while (!q.empty())q.pop();
for (int i=1;i<=scc;i++)
if (indeg[i]==0)
q.push(i);
while (!q.empty())
{
int u=q.front();
q.pop();
if (color[u]==0)
{
color[u]=1;
color[cf[u]]=2;
}
int sz=dag[u].size();
for (int i=0;i<sz;i++)
{
indeg[dag[u][i]]--;
if (indeg[dag[u][i]]==0)
q.push(dag[u][i]);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin);
#endif
int i,j,u,v,cas=0,t;
scanf("%d",&t);
while (t--)
{
scanf("%d%d",&m,&n);
init();
for (i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
if (u>0&&v>0)
{
u--,v--;
addedge(2*u+1,2*v);
addedge(2*v+1,2*u);
}
else if (u>0&&v<0)
{
v=-v;u--;v--;
addedge(2*u+1,2*v+1);
addedge(2*v,2*u);
}
else if (u<0&&v>0)
{
u=-u;u--;v--;
addedge(2*u,2*v);
addedge(2*v+1,2*u+1);
}
else
{
u=-u;v=-v;u--;v--;
addedge(2*u,2*v+1);
addedge(2*v,2*u+1);
}
}
printf("Case %d: ",++cas);
if (!solve(2*n)) printf("No\n");
else
{
topsort(2*n);
printf("Yes\n");
vector<int>ans;
for (i=0;i<2*n;i+=2)
if (color[Belong[i]]==1) ans.push_back(i/2+1);
printf("%d",ans.size());
for (i=0;i<ans.size();i++) printf(" %d",ans[i]);
printf("\n");
}
}
return 0;
}
PDF (English) | Statistics | Forum |
Time Limit: 2 second(s) | Memory Limit: 32 MB |
plan. The plan is that the voters are given a chance to vote again to form the new council. A vote will be like ±i ±j. '+' means the voter wants that member to be in the council, '-' means the voter doesn't
want the member to be in the council. For example, there are 4 voters, they voted like
+1 -3 the voter wants member 1 to be kept in the council or member 3 to be thrown out
+2 +3 the voter wants member 2 to be kept in the council or member 3 to be kept in the council
-1 -2 the voter wants member 1 to be thrown out or member 2 to be thrown out
-4 +1 the voter wants member 4 to be thrown out or member 1 to be kept in the council
A voter will be satisfied if at least one of his wishes becomes true. Now your task is to form the council such that all the voters are happy.
Input
Input starts with an integer T (≤ 20), denoting the number of test cases.Each case starts with a line containing two integers n (1 ≤ n ≤ 20000) and m (1 ≤ m ≤ 8000). Each of the next n lines contains a vote in the form ±i ±j (1 ≤ i, j ≤ m).
Output
For each case, print the case number and 'Yes' if a solution exists, or 'No' if there is no solution. Then if the result is yes, print another line containing the number of members in the council followed by the membersin ascending order. And print a single space between two numbers. There can be many solutions. Any valid one will do.
Sample Input | Output for Sample Input |
3 4 3 +1 +3 +2 -1 +2 -3 -1 -2 4 2 +1 -2 +1 +2 -1 -2 -1 +2 1 3 +1 -3 | Case 1: Yes 2 2 3 Case 2: No Case 3: Yes 0 |
Note
This is a special judge problem. Wrong output format may cause wrong answer.题意:n个公民m个议员,n个公民对m个公民进行投票,+i表示希望i号议员留下,-i希望i号议员离开,问是否存在一组解满足全部的n个投票,有的话输出任意一组解。
思路:每个公民的投票a||b建图,!a->b , !b->a。
代码:
#include <iostream>
#include <functional>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b) for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b) for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v) memset ((t) , v, sizeof(t))
#define sf(n) scanf("%d", &n)
#define sff(a,b) scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf printf
#define DBG pf("Hi\n")
typedef long long ll;
using namespace std;
#define INF 0x3f3f3f3f
#define mod 1000000009
const int maxn = 1005;
const int MAXN = 20005;
const int MAXM = 200010;
const int N = 1005;
struct Edge
{
int to,next;
}edge[MAXM];
int head[MAXN],tot;
void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
int n,m;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
int Index,scc,top;
bool Instack[MAXN];
void Tarjan(int u)
{
int v;
Low[u]=DFN[u]=++Index;
Stack[top++]=u;
Instack[u]=true;
for (int i=head[u];~i;i=edge[i].next)
{
v=edge[i].to;
if (!DFN[v])
{
Tarjan(v);
if (Low[u]>Low[v]) Low[u]=Low[v];
}
else if (Instack[v]&&Low[u]>DFN[v]) Low[u]=DFN[v];
}
if (Low[u]==DFN[u])
{
scc++;
do{
v=Stack[--top];
Instack[v]=false;
Belong[v]=scc;
}while (v!=u);
}
}
bool solve(int n)
{
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
Index=scc=top=0;
for (int i=0;i<n;i++)
if (!DFN[i]) Tarjan(i);
for (int i=0;i<n;i+=2)
if (Belong[i]==Belong[i^1])
return false;
return true;
}
queue<int>q;
vector<vector<int> >dag;
int color[MAXN];
int indeg[MAXN];
int cf[MAXN];
void topsort(int n)
{
dag.assign(scc+1,vector<int>());
memset(indeg,0,sizeof(indeg));
memset(color,0,sizeof(color));
for (int u=0;u<n;u++)
{
for (int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].to;
if (Belong[u]!=Belong[v])
{
dag[Belong[v]].push_back(Belong[u]);
indeg[Belong[u]]++;
}
}
}
for (int i=0;i<n;i+=2)
{
cf[Belong[i]]=Belong[i^1];
cf[Belong[i^1]]=Belong[i];
}
while (!q.empty())q.pop();
for (int i=1;i<=scc;i++)
if (indeg[i]==0)
q.push(i);
while (!q.empty())
{
int u=q.front();
q.pop();
if (color[u]==0)
{
color[u]=1;
color[cf[u]]=2;
}
int sz=dag[u].size();
for (int i=0;i<sz;i++)
{
indeg[dag[u][i]]--;
if (indeg[dag[u][i]]==0)
q.push(dag[u][i]);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin);
#endif
int i,j,u,v,cas=0,t;
scanf("%d",&t);
while (t--)
{
scanf("%d%d",&m,&n);
init();
for (i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
if (u>0&&v>0)
{
u--,v--;
addedge(2*u+1,2*v);
addedge(2*v+1,2*u);
}
else if (u>0&&v<0)
{
v=-v;u--;v--;
addedge(2*u+1,2*v+1);
addedge(2*v,2*u);
}
else if (u<0&&v>0)
{
u=-u;u--;v--;
addedge(2*u,2*v);
addedge(2*v+1,2*u+1);
}
else
{
u=-u;v=-v;u--;v--;
addedge(2*u,2*v+1);
addedge(2*v,2*u+1);
}
}
printf("Case %d: ",++cas);
if (!solve(2*n)) printf("No\n");
else
{
topsort(2*n);
printf("Yes\n");
vector<int>ans;
for (i=0;i<2*n;i+=2)
if (color[Belong[i]]==1) ans.push_back(i/2+1);
printf("%d",ans.size());
for (i=0;i<ans.size();i++) printf(" %d",ans[i]);
printf("\n");
}
}
return 0;
}
相关文章推荐
- [BZOJ1997][HNOI2010][2-sat]Planar
- [HDU3622][2-sat]Bomb Game
- HDU 3062 Party
- POJ 2723 Get Luffy Out
- 例题5.10 宇航员分组 LA3713
- 例题5.9 飞机调度 LA3211
- HDU 3062 Party 2-SAT 入门题
- HDU 3622 Bomb Game 2-sat
- POJ 3648 Wedding 2-SAT 输出任意一个2-sat解
- hdu3062 Party(2-SAT入门)
- hdu3622 Bomb Game(二分+2-SAT)
- HDU 3062 Party (2-sat)
- HDU 1824 Let's go home (2-SAT)
- HDU 3622 Bomb Game (二分+2-SAT)
- POJ 3683 Priest John's Busiest Day (2-SAT+输出可行解)
- POJ 3678 Katu Puzzle (2-SAT)
- POJ 3648 Wedding (2-SAT+输出可行解)
- LA 4452 The Ministers' Major Mess(2-SAT)
- 2-SAT模板(scc强连通模板)-poj3683-Priest John's Busiest Day
- uva1146 - Now or later