zoukankan      html  css  js  c++  java
  • bzoj 1894 游戏

    题目大意:

    $n$个装备,每个装备有两个值,可以攻击该值对应的怪兽。每个装备最多用一次

    每个怪兽被打一次之后就会死,每个怪兽可以被打当且仅当前面的都死了,求最多打多少个

    思路:

    很明显的二分图匹配,如果用$Dinic$的时候一条一条加入连向终点的边即可

    但是为什么这道题我$TLE$了啊 垃圾Dinic要你有何用,我也不(wang)会(le)匈牙利啊

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<queue>
     8 #include<vector>
     9 #include<map>
    10 #include<set>
    11 #define ll long long
    12 #define db double
    13 #define inf 2139062143
    14 #define MAXN 4010
    15 #define MOD 1000000007
    16 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
    17 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
    18 #define ren for(register int i=fst[x];i;i=nxt[i])
    19 #define pb(i,x) vec[i].push_back(x)
    20 #define pls(a,b) (a+b+MOD)%MOD
    21 #define mns(a,b) (a-b+MOD)%MOD
    22 #define mul(a,b) (1LL*(a)*(b))%MOD
    23 using namespace std;
    24 inline int read()
    25 {
    26     int x=0,f=1;char ch=getchar();
    27     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    28     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    29     return x*f;
    30 }
    31 int n,m,s,t;
    32 struct Dinic
    33 {
    34     int fst[MAXN],nxt[MAXN<<2],to[MAXN<<2],val[MAXN<<2],cnt;
    35     int S,T,vis[MAXN],tot,cur[MAXN],q[MAXN],l,r,dis[MAXN];
    36     Dinic(){memset(fst,0,sizeof(fst));cnt=1;}
    37     void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;} 
    38     void ins(int u,int v,int w) {add(u,v,w);add(v,u,0);}
    39     int bfs()
    40     {
    41         q[l=r=1]=T,vis[T]=++tot,dis[T]=0;int x;
    42         while(l<=r)
    43         {
    44             x=q[l++];cur[x]=fst[x];ren if(vis[to[i]]!=tot&&val[i^1])
    45                 vis[to[i]]=tot,dis[to[i]]=dis[x]+1,q[++r]=to[i];
    46         }
    47         return vis[S]==tot;
    48     }
    49     int dfs(int x,int a)
    50     {
    51         if(x==T||!a) return a;int f,flw=0;
    52         for(int& i=cur[x];i&&a;i=nxt[i]) 
    53             if(val[i]&&dis[to[i]]==dis[x]-1&&(f=dfs(to[i],min(a,val[i]))))
    54                 val[i]-=f,val[i^1]+=f,flw+=f,a-=f;return flw;
    55     }
    56     int solve(int s,int t,int res=0)
    57         {S=s,T=t;while(bfs()) res+=dfs(S,inf);return res;}
    58 }D;
    59 int main()
    60 {
    61     n=read(),m=read(),s=0,t=n+m+1;int a,b;rep(i,1,m)
    62         {a=read()+1,b=read()+1;D.ins(a,i+n,1);D.ins(b,i+n,1);}
    63     rep(i,1,n) D.ins(s,i,1);
    64     rep(i,1,m+1) {D.ins(i+n,t,1);if(!D.solve(s,t)) return printf("%d
    ",i-1),0;}
    65 }
    bzoj 1191 代码(与此题只是数据范围区别

    然后发现了奇妙的并查集做法

    对每个装备的两个值连边,若形成一个$x$个点的树,则我们可以选走$x-1$个点,留下最大的那个

    若成环,则都可以取。这样我们并查集合并即可,合并时找出最大的不行变成可以的

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<queue>
     8 #include<vector>
     9 #include<map>
    10 #include<set>
    11 #define ll long long
    12 #define db double
    13 #define inf 2139062143
    14 #define MAXN 1001000
    15 #define MOD 1000000007
    16 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
    17 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
    18 #define ren for(register int i=fst[x];i;i=nxt[i])
    19 #define pb(i,x) vec[i].push_back(x)
    20 #define pls(a,b) (a+b+MOD)%MOD
    21 #define mns(a,b) (a-b+MOD)%MOD
    22 #define mul(a,b) (1LL*(a)*(b))%MOD
    23 using namespace std;
    24 inline int read()
    25 {
    26     int x=0,f=1;char ch=getchar();
    27     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    28     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    29     return x*f;
    30 }
    31 int n,m,fa[MAXN],ok[MAXN];
    32 int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
    33 int main()
    34 {
    35     n=read(),m=10000;int a,b;rep(i,1,m) fa[i]=i;rep(i,1,n)
    36     {
    37         a=find(read()),b=find(read());if(a==b) {ok[a]=1;continue;}
    38         if(a>b) swap(a,b);ok[!ok[a]?a:b]=1,fa[a]=b;
    39     }rep(i,1,m+1) if(!ok[i]) return printf("%d
    ",i-1),0;
    40 }
    View Code
  • 相关阅读:
    算法>分支限界 小强斋
    C# DataGridView 的 CellValueChanged 与修改数据没保存的情况
    Windows8使用虚拟磁盘vhdx功能来为容量较大的文件夹扩容
    DataSet / DataTable 对 Access 数据库进行更改后,无法获取自动编号(自增)列的新值
    使用Windows Server 2012配置更新服务Update Service,以及客户端的配置
    在Windows 8中找回开始菜单
    DataSet / BindingSource / DataGridView / BindingNavigator 的关系与绑定、更新顺序
    Windows8 的搜狗输入法的快捷键推荐设置方法
    如果要使用DataAdapter来修改DataSet的子集时,请尽量对父级做修改。
    about PostgreSQL
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/10648429.html
Copyright © 2011-2022 走看看