最小路径覆盖合集

来源:互联网 发布:家庭网络拓扑 编辑:程序博客网 时间:2024/06/12 21:30

首先谈谈对最小路径覆盖核心函数的理解:每次从u出发寻找扩增点,若v已被其他点h扩增,则递归令h重新扩增另一个点,并把v的父节点指向h

int getNext(int u){    for (int i = head[u], v; i!= -1; i=next[i])    {        if ( !vis[v=to[i]])        {            vis[v] = 1;            if (fa[v] == -1 || getNext(fa[v]))            {                fa[v] = u;                return 1;            }        }    }    return 0;}


hdu 4606 Occupy Cities

图论(线段交叉),最小路径覆盖。。。。

貌似hdu的编译器有bug

#include <cstdio>  #include <cstring>  #include <iostream>  #include <cmath>  using namespace std; #define MAXN 310#define MAXM 100000int n, m, p;struct node{    int x, y;}data[MAXN];int seq[MAXN];double dis[MAXN][MAXN];int head[MAXN], to[MAXM], next[MAXM], szEdge;int vis[MAXN], fa[MAXN];void add(int u, int v){    to[szEdge] = v;    next[szEdge] = head[u];    head[u] = szEdge++;}int getNext(int u){    for (int i = head[u], v; i!= -1; i=next[i])    {        if ( !vis[v=to[i]])        {            vis[v] = 1;            if (fa[v] == -1 || getNext(fa[v]))            {                fa[v] = u;                return 1;            }        }    }    return 0;}inline double getDis(int i, int j){    return sqrt( (double)(data[i].x-data[j].x)*(data[i].x-data[j].x) + (double)(data[i].y-data[j].y)*(data[i].y-data[j].y));}inline int getCross(node &n0, node &n1, node &n2){    return (n1.x-n0.x)*(n2.y-n0.y) - (n1.y-n0.y)*(n2.x-n0.x);}int isCross(node a1, node a2, node b1, node b2){    int d1 = getCross(a1,a2,b1),    d2 = getCross(a1,a2,b2),    d3 = getCross(b1,b2,a1),    d4 = getCross(b1,b2,a2);    if(((d1>0&&d2<0)||(d1<0&&d2>0))&&((d3>0&&d4<0)||(d3<0&&d4>0)))        return 1;    return 0;}int main(){#ifndef ONLINE_JUDGE    freopen("in.txt", "r", stdin);#endif // ONLINE_JUDGE    int t, i;    scanf("%d", &t);    while (t--)    {                scanf("%d%d%d", &n, &m, &p);        int cnt = n + 2*m;        for ( i = 1; i<= n; ++i)            scanf("%d%d", &data[i].x, &data[i].y);        for (i = n+1; i<= cnt; ++i)            scanf("%d%d", &data[i].x, &data[i].y);        for (i = 1; i<= n; ++i)            scanf("%d", &seq[i]);        /// 初始化距离        for (i = 1; i<= cnt; ++i)        {            for (int j = i; j<= cnt; ++j)            {                if (i == j) dis[i][j] = 0.0;                else                {                    dis[j][i] = getDis(i,j);                    dis[i][j] = dis[j][i];                }            }        }        /// 判断交叉        for (i = 1; i<= cnt ; ++i)        {            for (int j = i+1; j<= cnt; ++j)            {                if (dis[i][j] < 0.0) continue;                for (int k = n+1; k <= cnt; k+=2)                {                    if (isCross(data[i],data[j],data[k],data[k+1]))                    {                        dis[i][j] = dis[j][i] = -1;                        break;                    }                }            }        }        /// floyd        for (i = 1; i<= cnt; ++i)            for (int j = 1; j<= cnt; ++j)                if (dis[j][i] != -1 )                for (int k = 1; k<= cnt; ++k)                    if (dis[i][k] != -1)                    {                        if (dis[j][k] == -1)                            dis[j][k] = dis[k][j] = dis[j][i] + dis[i][k];                        else if (dis[j][k] > dis[j][i] + dis[i][k])                            dis[j][k] = dis[k][j] = dis[j][i] + dis[i][k];                        }        double l = 0.0, r = 40000.0 , mid;        const double inf = 1e-6;        while (r-l > inf)        {            mid = (l+r)/2.0;            memset(head, -1, sizeof head);            memset(fa, -1, sizeof fa);            szEdge = 0;            for (i = 1; i<= n; ++i)                for (int j = i+1; j<= n; ++j)                    if (dis[seq[i]][seq[j]] != -1 && dis[seq[i]][seq[j]] <= mid)                        add(seq[i], seq[j]);            int tp = 0;            /// 最小路径覆盖            for (i = 1; i<= n; ++i)            {                memset(vis, 0, sizeof vis);                if (getNext(i))                    ++tp;            }            if (n-tp <= p) r = mid;            else l = mid;        }        printf("%.2lf\n", (l+r)/2.0);    }    return 0;}


hdu 4619 Warm up 2

匈牙利算法,但核心与最小路径覆盖一致,都是逐渐扩增

#include <stdio.h>#include <vector>#include <string.h>#include <math.h>using namespace std;#define MAXN 1005int fa[MAXN], vis[MAXN];struct _node{    int x, y;} dm[MAXN], dn[MAXN];vector<int> nxt[MAXN];int test ( int i, int j ){    _node a = dn[i], b = dm[j];    if ( a.x == b.x && a.y == b.y ) { return 1; }    if ( a.x + 1 == b.x && a.y == b.y ) { return 1; }    if ( a.x == b.x && a.y == b.y + 1 ) { return 1; }    if ( a.x + 1 == b.x && a.y == b.y + 1 ) { return 1; }    return 0;}int fnd ( int u ){    for ( unsigned int i = 0; i < nxt[u].size(); ++i )    {        int v = nxt[u][i];        if ( vis[v] ) { continue; }        vis[v] = 1;        if ( fa[v] == -1 || fnd ( fa[v] ) )        {            fa[v] = u;            return 1;        }    }    return 0;}int main(){#ifdef  __GNUC__    freopen ( "in.txt", "r", stdin );    //freopen ( "out.txt", "w", stdout );#endif // __GNUC__    int n, m;    while ( scanf ( "%d%d", &n , &m ) == 2 && ( m + n ) )    {        for ( int i = 0; i < n; ++i )        {            scanf ( "%d%d", &dn[i].x, &dn[i].y );            nxt[i].clear();        }        for ( int i = 0; i < m; ++i )        {            scanf ( "%d%d", &dm[i].x, &dm[i].y );        }        for ( int i = 0; i < n; ++i )        {            for ( int j = 0; j < m; ++j )            {                if ( test ( i, j ) )                {                    nxt[i].push_back ( j );                }            }        }        memset ( fa, -1, sizeof fa );        int cnt = 0;        for ( int i = 0; i < n; ++i )        {            memset ( vis, 0, sizeof vis );            if ( fnd ( i ) )            {                cnt++;            }        }        printf ( "%d\n", n + m - cnt );    }    return 0;}


hdu 1150 Machine Schedule

最小点覆盖

#include <stdio.h>#include <vector>#include <string.h>#include <math.h>using namespace std;#define MAXN 1005int fa[MAXN], vis[MAXN];struct _node{    int x, y;} dm[MAXN], dn[MAXN];vector<int> nxt[MAXN];int fnd ( int u ){    for ( unsigned int i = 0; i < nxt[u].size(); ++i )    {        int v = nxt[u][i];        if ( vis[v] ) { continue; }        vis[v] = 1;        if ( fa[v] == -1 || fnd ( fa[v] ) )        {            fa[v] = u;            return 1;        }    }    return 0;}int main(){#ifdef  __GNUC__    freopen ( "in.txt", "r", stdin );    //freopen ( "out.txt", "w", stdout );#endif // __GNUC__    int n, m, k;    while ( scanf ( "%d", &n ) && n )    {        scanf ( "%d%d", &m, &k );        for ( int i = 0; i < n; ++i )        {            nxt[i].clear();        }        for ( int i = 0, j; i < k; ++i )        {            int u, v;            scanf ( "%d%d%d", &j, &u, &v );            if ( u && v)                nxt[u].push_back ( v );        }        memset ( fa, -1, sizeof fa );        int cnt = 0;        for ( int i = 1; i < n; ++i )        {            memset ( vis, 0, sizeof vis );            if ( fnd ( i ) )            {                cnt++;            }        }        printf ( "%d\n",  cnt );    }    return 0;}


原创粉丝点击