@codeforces - 1186F VUS @コサックとグラフ


@説明@

図は、所与の(N、Mは<= 10 ^ 6)、点Nジに対するi番目のエッジ点Mの程度と呼びます。

今度は図ジ新たなi番目の点の(N + M)(切り上げ)/ 2の縁、及び必要な程度≥ジ「2DIを満たす」以下で維持させていません。

特定の解けることを証明するのは難しいことではありません。今、あなただけで任意のプログラムをエクスポートする必要があります。

入力
最初の行は、点とエッジの数を表し、nおよびmが含ま。
M 2 UI、VIの整数を含む各列の次の行は、エッジが記載されています。
リングからのヘビーエッジありません。

出力
予約最初の行番号kの第1の出力側。
次に、二つの整数U、Vによってk行の各列は、エッジが保持され記載されています。

サンプル入力
10 20
4 3
6 5
4 5
10 8
4 8
5 8
10 4
9 5
5 1
3 8
1 2
4 7
1 4
10 7
1 7
6 1
9 6
3 9
7 9
6 2
サンプル出力
12
2 1
4 1
5 4
5 6
7 1
7 4
8 3
8 5
9 3
9 6
10 4
10 7

@溶液@

グッド神秘的なタイトルああ。
しかし、私は同じではありませんが、アルゴリズムはほぼ同じに使用される標準的な数で達成するようだと思います。

タイトルも最小限度の新しいオリジナルの1/2程度によれば、奇数新しい最小次数(以前+1度)1/2。
特異エッジ保持の結合点を、さらにポイントの場合に、新しい度はすべての点で最小値をとる場合は、カップリングハーフエッジの結合点を半分に保持され、削除されます。
これは、あなたが何を考えてみましょうしていない、同じサイズの一連の操作の中にある点のエッジに接続されている議論のパリティサブプロセスの度合いを指します。

オイラーツアー。つまり、すべての側面からのパスをお見逃しなく、繰り返されません。
オイラー回路は、結合点側縁部に接続することができる「耳」と「エッジ」カテゴリの同じ数に分割されます。
同時にひとつ以上の縁端部に、ちょうど開始点よりも側、オイラー経路を開始する特異点特異点の最後に見出すことができます。
そうではありませんし、私達はちょうど議論してきたことを一致してどうなりますか?

オイラー回路を考えてみましょう、状況のない奇妙な点、すなわちません。
オイラーサイクル長が偶数の場合、我々は予約だけ片側、およびエッジの総数のエッジのすべての点が半分に低減されることを保証することができる側に障壁の片側を保持する必要があります。
長さのような奇数である場合にそうでない場合、(1,2)、(2,3)、(3、1)、我々は一の側の側縁部を保持するための第一区画から開始し、我々は最後に第1のストリップを残していることを見つけることができると両側に隣接している最後のものは、私たちは、元の総エッジ数プラス1 1/2に変化しました。
ない複数のエッジが存在しないので、奇数の長さは、2つの以上の点が含まれている必要があり、それは、N / 2回まで追加されます。問題を満たすために設定します。

即ち、始点と終点が奇数で、オイラー経路を考えます。
オイラーサイクル長は片側を維持する障壁の始端から、奇数である場合。エッジの総数が元の1/2プラス1となる(の奇数倍より保持の長さは省略)。
そうでなければ、など偶数、後の長さであれば(1,2)、(2,3)、(3,4)、(4,5)、始点からバリアの側縁部を保持し、次いで端縁に接続されました予約。エッジの総数は、1を加え、元の1/2になります。
nは奇数ドットまで、パスが各奇数の点との間に発生され、それはN / 2回まで追加されています。問題を満たすために設定します。

オイラーパスの数を解決する方法:小さな点を補完します。あなただけオフペアと奇数ドット仮想エッジコネクタ、オイラーを実行すると、2つの側面の間に介在するようにする仮想オイラー経路である必要があります。何の仮想エッジが存在しない場合はオイラーツアーです。

タイトルは、図通信に与えられないことに注意してください、あなたが操作される各ブロックと通信する必要があります。

@acceptedコード@

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1000000;
const int MAXM = 5000000;
struct edge{
    int from, to;
    bool flag, tag;
    edge *nxt, *rev;
}edges[MAXM + 5], *adj[MAXN + 5], *ecnt = &edges[0];
int fa[MAXN + 5];
int find(int x) {
    return fa[x] = (fa[x] == x ? x : find(fa[x]));
}
void addedge(int u, int v, bool t) {
    edge *p = (++ecnt), *q = (++ecnt);
    p->from = u, p->to = v, p->nxt = adj[u], adj[u] = p;
    q->from = v, q->to = u, q->nxt = adj[v], adj[v] = q;
    p->flag = q->flag = false, p->tag = q->tag = t;
    p->rev = q, q->rev = p;
    if( find(u) != find(v) )
        fa[find(u)] = find(v);
}
int deg[MAXN + 5]; edge *e[MAXM + 5], *tmp[MAXM + 5];
int ans1[MAXM + 5], ans2[MAXM + 5];
int cnt, tot;
void dfs(int x) {
    for(edge *p=adj[x];p;p=adj[x]) {
        if( p->flag ) {
            adj[x] = adj[x]->nxt;
            continue;
        }
        p->flag = p->rev->flag = true;
        adj[x] = adj[x]->nxt; dfs(p->to); e[++cnt] = p;
    }
}
void print() {
    printf("%d\n", tot);
    for(int i=1;i<=tot;i++)
        printf("%d %d\n", ans1[i], ans2[i]);
}
int main() {
    int n, m; scanf("%d%d", &n, &m);
    for(int i=1;i<=n;i++)
        fa[i] = i;
    for(int i=1;i<=m;i++) {
        int u, v; scanf("%d%d", &u, &v);
        addedge(u, v, true); deg[u]++, deg[v]++;
    }
    int lst = 0, fir = 0;
    for(int i=1;i<=n;i++) {
        if( deg[i] & 1 ) {
            if( !lst ) lst = i;
            else addedge(lst, i, false), lst = 0;
        }
    }
    for(int i=1;i<=n;i++) {
        if( find(i) != i ) continue;
        cnt = lst = fir = 0; dfs(i);
        for(int j=1;j<=cnt;j++) {
            if( !e[j]->tag ) {
                if( lst ) {
                    int siz = 0;
                    for(int k=lst+1;k<=j-1;k++)
                        tmp[++siz] = e[k];
                    if( siz && siz % 2 == 0 ) tmp[siz+1] = tmp[siz], siz++;
                    for(int k=1;k<=siz;k+=2)
                        tot++, ans1[tot] = tmp[k]->from, ans2[tot] = tmp[k]->to;
                    if( siz && siz % 2 == 0 )
                        tot++, ans1[tot] = tmp[siz]->from, ans2[tot] = tmp[siz]->to;
                }
                else fir = j;
                lst = j;
            }
        }
        if( !lst ) {
            for(int j=1;j<=cnt;j+=2)
                tot++, ans1[tot] = e[j]->from, ans2[tot] = e[j]->to;
        }
        else {
            int siz = 0;
            for(int j=lst+1;j<=cnt;j++)
                tmp[++siz] = e[j];
            for(int j=1;j<=fir-1;j++)
                tmp[++siz] = e[j];
            if( siz && siz % 2 == 0 ) tmp[siz+1] = tmp[siz], siz++;
            for(int j=1;j<=siz;j+=2)
                tot++, ans1[tot] = tmp[j]->from, ans2[tot] = tmp[j]->to;
        }
    }
    print();
}

@詳細@

タイトルは言うもののソリューションは、非常に自然なようです。
あなたが考えることができる場合でも、実行する際のゲームCaiyouグイわかりました。

タグによってヒットオイラー道が側意志TLEを訪問したマーク。現在のアークでの類推のネットワークフローの最適化を必要とし、訪問側が直接削除します。

おすすめ

転載: www.cnblogs.com/Tiw-Air-OAO/p/11114236.html