现在的位置: 首页 > 综合 > 正文

线性规划与网络流24题

2013年12月04日 ⁄ 综合 ⁄ 共 3690字 ⁄ 字号 评论关闭

1.飞行员配对方案问题 二分匹配

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int NN=110;

int n,m,match[NN];
bool mp[NN][NN],used[NN];

bool dfs(int u)
{
    for (int v=1; v<=m; v++) if (mp[u][v])
    {
        if (used[v]) continue;
        used[v]=1;
        if (match[v]==-1 || dfs(match[v]))
        {
            match[v]=u;
            return true;
        }
    }
    return false;
}

void hungary()
{
    memset(match,-1,sizeof(match));

    int cnt=0;
    for (int i=1; i<=n; i++)
    {
        memset(used,0,sizeof(used));
        if (dfs(i)) cnt++;
    }

    if (cnt==0) puts("No Solution!");
    else
    {
        printf("%d\n",cnt);
        for (int i=1; i<=m; i++) if (match[i]!=-1)
        {
            printf("%d %d\n",match[i],i);
        }
    }
}

int main()
{
    int u,v;

    scanf("%d%d",&n,&m);
    memset(mp,0,sizeof(mp));
    while (scanf("%d%d",&u,&v)==2 && u!=-1 && v!=-1)
    {
        mp[u][v]=1;
    }

    hungary();

    return 0;
}

2.太空飞行计划问题 最大权闭包

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;

const int NN=888;
const int MM=888888;
const int INF=888888888;

int S,T,NV,en,head[NN];
struct Edge
{
    int u,v,f,next;
    Edge() {}
    Edge(int _u,int _v,int _f,int _next):u(_u),v(_v),f(_f),next(_next) {}
} e[MM];
void add(int u,int v,int f)
{
    e[en]=Edge(u,v,f,head[u]);
    head[u]=en++;
    e[en]=Edge(v,u,0,head[v]);
    head[v]=en++;
}

int gap[NN],dis[NN],cur[NN],pre[NN];
int sap()
{
    int ret=0;
    for (int i=0; i<NV; i++)
    {
        cur[i]=head[i];
        dis[i]=gap[i]=0;
    }

    int aug=0;
    int u=pre[S]=S;
    gap[0]=NV;
    while (dis[S]<NV)
    {
loop:
        for (int &i=cur[u]; i!=-1; i=e[i].next)
        {
            int v=e[i].v;
            if (e[i].f && dis[u]==dis[v]+1)
            {
                if (e[i].f<aug) aug=e[i].f;
                pre[v]=u;
                u=v;
                if (u==T)
                {
                    ret+=aug;
                    for (u=pre[u]; v!=S; v=u,u=pre[u])
                    {
                        e[cur[u]].f-=aug;
                        e[cur[u]^1].f+=aug;
                    }
                    aug=INF;
                }
                goto loop;
            }
        }

        int min_dis=NV;
        for (int i=head[u]; i!=-1; i=e[i].next)
        {
            int v=e[i].v;
            if (e[i].f>0 && dis[v]<min_dis)
            {
                min_dis=dis[v];
                cur[u]=i;
            }
        }

        if (--gap[dis[u]]==0) break;
        gap[dis[u]=min_dis+1]++;
        u=pre[u];
    }

    return ret;
}

bool f[NN];
void dfs(int u)
{
    f[u]=true;
    for (int i=head[u]; i!=-1; i=e[i].next)
    {
        if (e[i].f && !f[e[i].v]) dfs(e[i].v);
    }
}

vector<int> vec[NN];
int main()
{
    int m,n,w,x;
    char c;

    en=0;
    memset(head,-1,sizeof(head));

    scanf("%d%d",&m,&n);
    S=0;
    T=m+n+1;
    NV=T+1;

    int sum=0;
    for (int i=1; i<=m; i++)
    {
        scanf("%d",&w);
        sum+=w;
        add(S,i,w);
        while (1)
        {
            while (c=getchar(),!isdigit(c) && c!='\n');
            if (c=='\n') break;
            x=c-'0';
            c=getchar();
            while (isdigit(c)) x=x*10+c-'0',c=getchar();
            vec[i].push_back(x);
            if (c=='\n') break;
        }
    }
    for (int i=1; i<=n; i++)
    {
        scanf("%d",&w);
        add(i+m,T,w);
    }
    for (int i=1; i<=m; i++)
        for (int j=0; j!=vec[i].size(); j++) add(i,vec[i][j]+m,INF);

    int ans=sum-sap();
    memset(f,0,sizeof(f));
    dfs(S);

    bool flag=0;
    for (int i=1; i<=m; i++) if (f[i])
    {
        if (!flag) flag=1;
        else       printf(" ");
        printf("%d",i);
    }
    puts("");
    flag=0;
    for (int i=1; i<=n; i++) if (f[i+m])
    {
        if (!flag) flag=1;
        else       printf(" ");
        printf("%d",i);
    }
    printf("\n%d\n",ans);

    return 0;
}

3.软件补丁问题 最短路dij

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;

const int NN=110;
const int MM=1100000;

int n,m,w[NN],b1[NN],b2[NN],f1[NN],f2[NN];
int dis[MM];
bool vis[MM];

struct node{
    int v;
    node () {}
    node(int _v): v(_v) {}
    bool operator <(const node a)const{
        return dis[a.v]<dis[v];
    }
};

bool match(int x,int i)
{
    for (int j=0; j<n; j++)
    {
        if ( (b1[i]&(1<<j)) && !(x&(1<<j)) ) return 0;
        if ( (b2[i]&(1<<j)) && (x&(1<<j)) ) return 0;
    }
    return 1;
}

int patch(int x,int i)
{
    int y=x;
    for (int j=0; j<n; j++)
    {
        if (f1[i]&(1<<j)) y|=1<<j;
        if (f2[i]&(1<<j)) y&=~(1<<j);
    }

    return y;
}

priority_queue<node> q;
int dij()
{
    memset(dis,0x7f,sizeof(dis));
    memset(vis,0,sizeof(vis));

    dis[(1<<n)-1]=0;
    q.push(node((1<<n)-1));

    while (!q.empty())
    {
        int u=q.top().v; q.pop();

        if (u==0) return dis[u];
        if (vis[u]) continue;
        vis[u]=true;
        //printf("%d %d\n",u,dis[u]);
        for (int i=1; i<=m; i++) if (match(u,i))
        {
            int v=patch(u,i);//printf("v: %d,%d\n",v,i);
            if (dis[v]>dis[u]+w[i])
            {
                dis[v]=dis[u]+w[i];
                q.push(node(v));
            }
        }
    }

    return 0;
}

char s1[32],s2[32];
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1; i<=m; i++)
    {
        scanf("%d%s%s",&w[i],s1,s2);
        b1[i]=b2[i]=0;
        for (int j=0; j<n; j++)
        {
            if (s1[j]=='+') b1[i]|=1<<j;
            if (s1[j]=='-') b2[i]|=1<<j;
        }
        f1[i]=f2[i]=0;
        for (int j=0; j<n; j++)
        {
            if (s2[j]=='+') f1[i]|=1<<j;
            if (s2[j]=='-') f2[i]|=1<<j;
        }
    }
    printf("%d\n",dij());

    return 0;
}

待续。。。

抱歉!评论已关闭.