URAL 2089 Experienced coach Twosat

Description

Misha trains several ACM teams at the university. He is an experienced coach, and he does not underestimate the meaning of friendly and collaborative atmosphere during training sessions. It used to be that way, but one of the teams happened to win contests a little bit more often than others, and hence became slightly too big for their boots. That does not contribute to positive spirit which is essential for successful training. But Misha knows what to do!

Representatives of k teams participate in Misha’s training sessions, each team has three members. Alas, teams rarely attend en masse, but at least one member per team is always present, of course. During the next training session Misha is going to split everyone into npairs, so that each pair will include representatives of different teams. Players will play a mini-contest against each other in each pair.

A situation when no two mini-contests are won by representatives of one team is the one that suits Misha’s goals best. He may be somewhat cunning when selecting winner in each pair in order to achieve such situation. Find out whether Misha will succeed.

Input

The first line contains two numbers — n and k (1 ≤ n ≤ 10 5, 2 ≤ k ≤ 10 5). n lines follow. i-th of these contains two numbers x iy i (1 ≤ x iy i ≤ kx i ≠ y i) — the numbers of teams, whose representatives are in pair number i.

It is guaranteed that each team is represented in no less than one and no more than three pairs.

Output

If Misha is to succeed, output Yes in the first line. In each of the following n lines output one number — the number of team that is to win in the corresponding pair. If there are several answers, output any.

If Misha is to fail, output No in the only line.

Sample Input

input output
3 4
1 2
2 3
1 4
Yes
2
3
4
6 4
1 2
1 3
1 4
2 3
2 4
3 4
No

题意:给出n对点a,b  要求从没对点中选出一个,且最终选出的点n个数不能存在相同的。输入数据满足每种数最多出现3次,最少出现1次

思路:第i对点的编号2*i, 2*i+1,   因为每个数最多出现3次,那么完全可以枚举每个数,然后相同的数之间的编号连一条边,表示这两个编号不能同时选,这样跑完twosat就能得到一个满足情况的解或无解。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdlib>
#include <map>
#include <set>
#include <cmath>
using namespace std;
const int N = 2e6 + 100;
struct Edge {
    int to, nex;
}e[N];
int head[N], tot;
void init() {
    tot = 0; memset(head, -1, sizeof head);
}
void add(int u, int v) {
    e[tot].to = v;
    e[tot].nex = head[u];
    head[u] = tot++;
}
int Low[N], DFN[N], Stack[N], Belong[N];
int Index, top;
int scc;
bool Instack[N];
int num[N];

void Tarjan(int u) {
    int v;
    Low[u] = DFN[u] = ++Index;
    Stack[top++] = u;
    Instack[u] = true;

    for(int i = head[u]; ~i; i = e[i].nex) {
        v = e[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;
            num[scc]++;
        }while(v != u);
    }
}
bool solvable(int n) {
    memset(DFN, 0, sizeof DFN);
    memset(Instack, false, sizeof Instack);
    memset(num, 0, sizeof num);
    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> q1, q2;
vector<vector<int> >dag;
int vis[N];
int indeg[N];
int cf[N];
void solve(int n) {
    dag.assign(scc+1, vector<int>());
    memset(indeg, 0, sizeof indeg);
    memset(vis, 0, sizeof vis);
    for(int u = 0; u < n; ++u) {
        for(int i = head[u]; ~i; i = e[i].nex) {
            int v = e[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(!q1.empty()) q1.pop();
    while(!q2.empty()) q2.pop();
    for(int i = 1; i <= scc; ++i) if(indeg[i] == 0) q1.push(i);

    while(!q1.empty()) {
        int u = q1.front();
        q1.pop();
        if(vis[u] == 0) {
            vis[u] = 1;
            vis[ cf[u] ] = 0;
        }
        int sz = dag[u].size();
        for(int i = 0; i < sz; ++i) {
            indeg[ dag[u][i] ]--;
            if(indeg[ dag[u][i] ] == 0) q1.push(dag[u][i]);
        }
    }
}
int r[N];
vector<int> g[N];
int main() {
#ifdef LOCAL
    freopen("in", "r", stdin);
#endif
    int n, m;
    while(~scanf("%d%d", &m, &n)) {
        init();
        int tot = 0; int u, v;
        for(int i = 0; i < m; ++i) {
            scanf("%d%d", &u, &v);
            r[tot++] = u;
            r[tot++] = v;
            g[u].push_back(2 * i);
            g[v].push_back(2 * i + 1);
        }

        for(int i = 1; i <= n; ++i) {
            int sx = g[i].size();
            for(int j1 = 0; j1 < sx; ++j1) {
                for(int j2 = j1 + 1; j2 < sx; ++j2) {
                    int v1 = g[i][j1];
                    int v2 = g[i][j2];
                    add(v1, v2 ^ 1);
                    add(v2, v1 ^ 1);
                }
            }
        }
        if(solvable(2 * m)) {
            solve(2 * m);
            puts("Yes");
            for(int i = 0; i < m; ++i) {
                if(vis[ Belong[2 * i] ]) printf("%d\n", r[2 * i + 1]);
                else printf("%d\n", r[2 * i]);
            }
        }else puts("No");
    }
    return 0;
}
时间: 2024-08-09 06:19:10

URAL 2089 Experienced coach Twosat的相关文章

【2-SAT】URAL - 2089 - Experienced coach

题意:给出n对点a,b  要求从没对点中选出一个,且最终选出的点n个数不能存在相同的.输入数据满足每种数最多出现3次,最少出现1次 思路:第i对点的编号2*i, 2*i+1,   因为每个数最多出现3次,那么完全可以枚举每个数,然后相同的数之间的编号建立关系(?a Λ ?b 为真,表示这两个编号不能同时选), 然后同一对的俩编号之间也有关系(a xor b为真,代表a和b必须选且只能选一个,a xor b 可以写成 (a V b) Λ (?a V ?b)),这样跑完twosat就能得到一个满足情

URAL 2005. Taxi for Programmers (最短路 数学啊)

题目链接:http://acm.timus.ru/problem.aspx?space=1&num=2005 2005. Taxi for Programmers Time limit: 0.5 second Memory limit: 64 MB The clock shows 11:30 PM. The sports programmers of the institute of maths and computer science have just finished their trai

URAL 1873. GOV Chronicles

唔 神题一道 大家感受一下 1873. GOV Chronicles Time limit: 0.5 secondMemory limit: 64 MB A chilly autumn night. Well wrapped up in a coat, a man is rapidly walking along a gray street. This is the Tradition Keeper of the ACM club in Ural State University. Drizzl

Ural 1081 Binary Lexicographic Sequence(DP)

题目地址:Ural 1081 先用dp求出每个长度下的合法序列(开头为1)的个数.然后求前缀和.会发现正好是一个斐波那契数列.然后每次判断是否大于此时长度下的最少个数,若大于,说明这一位肯定是1,若小于,则肯定是0.就这样不断输出出来即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #in

URAL 1684. Jack&#39;s Last Word KMP

题目来源:URAL 1684. Jack's Last Word 题意:输入a b 把b分成若干段 每一段都是a的前缀 思路:b为主串 然后用a匹配b 记录到b的i位置最大匹配的长度 然后分割 分割的时候要从后往前 如果a = abac b = abab 那么如果从前往后 首先覆盖了aba 然后b就不能覆盖了 从后往前就可以了 首先覆盖ab 下一次还是ab 因为已经记录了到i位置的最大匹配长度 根据长度从末尾倒退 每次倒退的时候只要是最大的匹配的长度 因为如果在某一次的递推 记录的最大匹配的前缀

【数位DP】HDU 2089 不要62

http://acm.hdu.edu.cn/showproblem.php?pid=2089 [AC] 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e6+2; 5 int dp[10][10]; 6 int digit[10]; 7 int cnt; 8 int ans; 9 int n,m; 10 bool check() 11 { 12 for(int

ural 1272. Non-Yekaterinburg Subway

1272. Non-Yekaterinburg Subway Time limit: 1.0 secondMemory limit: 64 MB A little town started to construct a subway. The peculiarity of the town is that it is located on small islands, some of them are connected with tunnels or bridges. The mayor is

ural 1273. Tie

1273. Tie Time limit: 1.0 secondMemory limit: 64 MB The subway constructors are not angels. The work under the ground and… Well, they are not angels. And where have you seen angels? It is all in a lifetime! Show me first somebody who has never… and t

ural 1269. Obscene Words Filter

1269. Obscene Words Filter Time limit: 0.5 secondMemory limit: 8 MB There is a problem to check messages of web-board visitors for the obscene words. Your elder colleagues commit this problem to you. You are to write a program, which check if there i