【UOJは#389] [UNR#3ハト(オイラー、コストフロー)

ポータルUOJ

質問が意図される:
2点が非接続辺の数に与えられている間に、2次元平面上のいくつかの点を与えます。
今から(1 \)\最終的バックに一度各エッジの後、ポイント番号を起動し、\(1 \)ドット。ラップの最大数の起源、最終的な時計回りの回転について尋ねます。

アイデア:

  • これは光線である反時計回りの回数を引いた後、この線を通じて閉じた図形でなければなりません最後に行くようにするので、悪い検討する原点時計回りに円を描くについてのストレートだと思うので、私たちは簡単に線を見つけることができ、時計回りの最終的な数答えます。
  • オイラーツアーがあるかどうかを確認することは非常に簡単です。
  • その後、我々はラップの最大数に来ます。私たちは、最初の貪欲各辺が時計回りに行くことであることを、側に向かうが、これは最後のオイラーツアーから抜け出す可能性があり、明らかです。
  • だから我々はいくつかの裏側を必要とし、このエッジのコストは、答えの寄与が乗算されている\(2 \)
  • 最後に、接続元シンクの程度に応じて、ライン上の最小コスト・フローを実行します。

最後に、我々は確かに反対側の数のために提供する必要があるため、必要に、ジョブの最大流量を取得する理由として、我々はまた、最小コストの最大流量となるよう、最小コストを取得する必要があります。
これはであるこの質問のように、コスト以上のものです。
いくつかの孤立点が存在し、その後もオイラーツアーがあってもよいがあってもよい、留意されたいです。

#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
//#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

int n, m;
int x[N], y[N];

int head[N],vis[N],d[N],a[N],pa[N],pre[N];
struct Edge{
    int v,next,c,w;
}e[N];
int tot ;
void adde(int u,int v,int c,int w){
    e[tot].v=v;e[tot].next=head[u];e[tot].w=w;e[tot].c=c;head[u]=tot++;
    e[tot].v=u;e[tot].next=head[v];e[tot].w=-w;e[tot].c=0;head[v]=tot++;
}
int spfa(int s,int t,int &flow,int &cost){
    for(int i=0;i<=t;i++) d[i]=a[i]=INF;d[s]=0;
    memset(vis,0,sizeof(vis));vis[s]=1;
    memset(pre,-1,sizeof(pre));memset(pa,-1,sizeof(pa));
    queue <int> q;q.push(s);
    while(!q.empty()){
        int u=q.front();q.pop();vis[u]=0;
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(e[i].c>0 && d[v]>d[u]+e[i].w){
                d[v]=d[u]+e[i].w;
                pa[v]=u;pre[v]=i;
                a[v]=min(a[u],e[i].c);
                if(!vis[v]){
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    if(d[t]==INF) return 0;
    flow+=a[t];
    cost+=a[t]*d[t];
    for(int i=t;i!=-1;i=pa[i]){
        int edge = pre[i];
        e[edge].c-=a[t];
        e[edge^1].c+=a[t];
    }
    return 1;
}
int Min_cost(int s,int t){
    int flow=0,cost=0;
    while(spfa(s,t,flow,cost));
    return cost;
}

int f[N];
int find(int x) {return f[x] == x ? f[x] : f[x] = find(f[x]);}
void Union(int x, int y) {
    int fx = find(x), fy = find(y);
    if(fx != fy) f[fx] = fy;
}
int deg[N];
void run() {
    for(int i = 1; i <= n; i++) {
        cin >> x[i] >> y[i];
    }
    memset(head, -1, sizeof(head));
    int ans = 0;
    for(int i = 1; i <= n; i++) f[i] = i;
    for(int i = 1; i <= m; i++) {
        int u, v; cin >> u >> v;
        if(1ll * x[u] * y[v] > 1ll * x[v] * y[u]) swap(u, v);
        //u -> v
        ++deg[u], --deg[v];
        Union(u, v);
        int val = (y[u] > 0 && y[v] <= 0);
        adde(u, v, 1, 2 * val);
        ans += val;
        vis[u] = vis[v] = true;
    }
    for(int i = 1; i <= n; i++) {
        if(vis[i] && find(i) != find(1)) {
            cout << -1 << '\n';
            return;
        }
    }
    for(int i = 1; i <= n; i++) {
        if(deg[i] & 1) {
            cout << -1 << '\n';
            return;
        }
    }
    int S = 0, T = n + 1;
    for(int i = 1; i <= n; i++) {
        if(deg[i] > 0) {
            adde(S, i, deg[i] / 2, 0);
        } else if(deg[i] < 0) {
            adde(i, T, -deg[i] / 2, 0);
        }
    }
    ans -= Min_cost(S, T);
    cout << ans << '\n';
}

int main() {
//    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
#ifdef Local
    freopen("../input.in", "r", stdin);
    freopen("../output.out", "w", stdout);
#endif
    while(cin >> n >> m) run();
    return 0;
}

おすすめ

転載: www.cnblogs.com/heyuhhh/p/11735142.html
おすすめ