傳送門
可以二分變成直接求最大鏈覆蓋,因為可以重復經過一個點
floydfloydfloyd傳遞閉包就可以了
#include<bits/stdc++.h>
using namespace std
;
#define ll long long
inline int read(){char ch
=getchar();int res
=0,f
=1;while(!isdigit(ch
)){if(ch
=='-')f
=-f
;ch
=getchar();}while(isdigit(ch
))res
=res
*10+(ch
^48),ch
=getchar();return res
*f
;
}
const int N
=55;
const int M
=505;
int f
[M
][M
];
int mat
[M
],val
[M
],n
,m
,mx
;
bool vis
[M
];
inline void floyd(){for(int k
=1;k
<=m
;k
++){for(int i
=1;i
<=m
;i
++){for(int j
=1;j
<=m
;j
++){f
[i
][j
]|=f
[i
][k
]&f
[k
][j
];}}}
}
inline bool dfs(int u
,int k
){for(int i
=1;i
<=m
;i
++)if(val
[i
]<k
&&f
[u
][i
]&&!vis
[i
]){vis
[i
]=1;if((!mat
[i
])||dfs(mat
[i
],k
)){mat
[i
]=u
;return 1;}}return 0;
}
inline bool check(int x
){memset(mat
,0,sizeof(mat
));int tot
=0,num
=0;for(int i
=1;i
<=m
;i
++){if(val
[i
]<x
){num
++,memset(vis
,0,sizeof(vis
));if(dfs(i
,x
))tot
++;}}return num
-tot
<=n
+1;
}
int main(){n
=read(),m
=read();for(int i
=1;i
<=m
;i
++){val
[i
]=read();int k
=read();mx
=max(mx
,val
[i
]);for(int j
=1;j
<=k
;j
++){int v
=read();f
[i
][v
]=1;}}floyd();int l
=1,r
=mx
,res
=mx
;while(l
<=r
){int mid
=(l
+r
)>>1;if(check(mid
))res
=mid
,l
=mid
+1;else r
=mid
-1;}if(res
==mx
)puts("AK");else cout
<<res
;
}
轉載于:https://www.cnblogs.com/stargazer-cyk/p/11145651.html
總結
以上是生活随笔為你收集整理的【BZOJ5335】【TJOI2018】—智力竞赛(floyd传递闭包+二分图匹配)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。