http://www.lydsy.com/JudgeOnline/problem.php?id=1854
https://www.luogu.org/problemnew/show/P1640
lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示。当他使用某种装备时,他只能使用该装备的某一个属性。并且每种装备最多只能使用一次。游戏进行到最后,lxhgww遇到了终极boss,这个终极boss很奇怪,攻击他的装备所使用的属性值必须从1开始连续递增地攻击,才能对boss产生伤害。也就是说一开始的时候,lxhgww只能使用某个属性值为1的装备攻击boss,然后只能使用某个属性值为2的装备攻击boss,然后只能使用某个属性值为3的装备攻击boss……以此类推。现在lxhgww想知道他最多能连续攻击boss多少次?
莫名奇妙的就想到了一个模型,然后脑子瓦特了的情况下竟然写了个正解但是不会论证,emmm……
考虑过权值和权值建边(然而会有重编一定不行),物品和物品建边(显然你不知道属性值了一定不行)。
那就物品和权值建边,对于权值分别向物品连有向边然后跑匈牙利算法即可。
为什么呢?显然,当我们尝试去匹配第i个属性的时候,i-1已经匹配完毕,如果i不能匹配的话就跳出并且输出i-1即可。
(PS:bzoj玩家请注意,不要每次dfs清空vis数组因为这样时间复杂度就不对了,所以需要优化)
#include<cmath> #include<cstdio> #include<cctype> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=1000010; const int M=10010; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct node{ int to,nxt; }e[N*2]; int n,m,ans,cnt; int shu[N],head[M],vis[N]; inline void add(int u,int v){ e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt; } bool dfs(int u,int id){ for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(vis[v]!=id){ vis[v]=id; if(!shu[v]||dfs(shu[v],id)){ shu[v]=u; return 1; } } } return 0; } int main(){ n=read();m=M-10; for(int i=1;i<=n;i++){ add(read(),i);add(read(),i); } for(int i=1;i<=m;i++){ if(dfs(i,i))ans++; else break; } printf("%d ",ans); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++