• 牛客20648 国政议事


    传送门

    分析

    不难想到将发出任务的和执行任务的分别建边然后连边得到一个二分图

    所以最优方案就是最大匹配

    那么如何判断哪些任务是必须的呢

    我们可以考虑枚举这m条边,如果删除第i条之后最大匹配减小则这条边必选

    注意在work函数中先判断是否存在这条边再判断他知否已经匹配过可以比反过来的运行速度快

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<map>
    #include<vector>
    using namespace std;
    int g[502][502];
    int used[502],wh[502];
    int t,n,m,x[20010],y[20010];
    inline bool work(int now){
        register int i,j,k;
        for(j=1;j<=n;++j)
           if(g[now][j]&&used[j]!=t){
               used[j]=t;
               if(!wh[j]||work(wh[j])){
                   wh[j]=now;
                   return 1;
               }
        }
        return 0;
    }
    inline int go(){
        register int i,j,k,ans=0;
        for(i=1;i<=n;++i){
            ++t;
            ans+=work(i);
        }
        return ans;
    }
    int pr[20010],cnt;
    inline int ra(){
        int x=0;char s=getchar();
        while(!isdigit(s))s=getchar();
        while(isdigit(s))x=(x<<3)+(x<<1)+(s-'0'),s=getchar();
        return x;
    }
    int main(){
        register int i,j,k;
        n=ra(),m=ra();
        for(i=1;i<=m;++i){
            x[i]=ra(),y[i]=ra();
            g[x[i]][y[i]]++;
        }
        int Ans=go();
        for(i=1;i<=m;++i){
          g[x[i]][y[i]]--;
          memset(wh,0,sizeof(wh));
          if(go()<Ans)pr[++cnt]=i;
          g[x[i]][y[i]]++;
        }
        printf("%d %d
    ",Ans,cnt);
        for(i=1;i<=cnt;i++)printf("%d
    ",pr[i]);
        return 0;
    }
  • 相关阅读:
    循序渐进学习XHTML
    一些常用正则表达式
    输入框限制
    Oracle 取随机数
    安装部署中的数据库打包和快捷方式启动浏览器
    游标小例
    查询列数
    临时表简介
    Update动态更新
    sql 多列转一列
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/10351747.html
Copyright © 2020-2023  润新知