暑假集训-二分图,网络流,2-SAT
匈牙利算法DFS
bool dfs(int u){
for(int i = ; i <= n; i++){
if(a[u][i] && !visit[i]){
visit[i] = true;
if(match[i] == - || dfs(match[i])){
match[i] = u;
}
return true;
}
}
return false;
}
最优匹配KM算法
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define LL long long
#define eps 1e-8
#define INF 0x3f3f3f3f
#define OPEN_FILE
#define MAXM 1005
#define MAXN 205
using namespace std;
int n, m;
char s[MAXN][MAXM];
int a[MAXN][MAXN], match[MAXN], fx[MAXN], fy[MAXN];
bool x[MAXN], y[MAXN]; bool dfs(int u){
x[u] = true;
for(int i = ; i <= n; i++){
if(y[i]) continue;
int p = fx[u] + fy[i] - a[u][i];
if(p == ){
y[i] = true;
if(match[i] == - || dfs(match[i])){
match[i] = u;
return true;
}
}else{
m = min(m, p);
}
}
return false;
}
void KM(){
int i,j;
memset(fx,,sizeof(fx));
memset(fy,,sizeof(fy));
memset(match,-,sizeof(match));
for(int i = ; i <= n; i++){
for(int j = ; j <= n; j++){
if(a[i][j] > fx[i]){
fx[i] = a[i][j];
}
}
}
for(int i = ; i <= n; i++){
while(true){
memset(x, , sizeof(x));
memset(y, , sizeof(y));
m = INF;
if(dfs(i)) break;
for(int j = ; j <= n; j++){
if(x[j]) fx[j] -= m;
if(y[j]) fy[j] += m;
}
}
}
}
int main()
{
#ifdef OPEN_FILE
//freopen("inD.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif // OPEN_FILE
while(~scanf("%d", &n)){
memset(a, , sizeof(a));
for(int i = ; i <= n; i++){
scanf("%s", s[i]);
}
for(int i = ; i <= n; i++){
int p = strlen(s[i]);
for(int j = ; j <= n; j++){
if(i == j) continue;
int q = strlen(s[j]) - ;
int cnt = ;
while(cnt < p && q >= && s[i][cnt] == s[j][q]){
cnt++;
q--;
}
a[i][j] = cnt;
}
}
KM();
int ans = ;
for(int i = ; i <= n; i++){
ans += a[match[i]][i];
}
printf("%d\n", ans);
}
}
2-SAT
这里面的add_clause的作用式是针对 x=xval or y=yval的时候加边,建不同的图要加不同的边,这里要注意下!!
比如还有一个经典的题目 HDU1824, 建图的时候要格外注意.对于前面队内关系来说是相互的,必须要有一个留下,但是对于队友关系来说却不是相互的,之存在A留B走而不存在A走B必须留的情况,所以加边的里面要写成单向的.
struct TwoSAT{
int n;
vector<int> G[MAXN*];
bool mark[MAXN*];
int S[MAXN*], c;
bool dfs(int x){
if(mark[x^]) return false;
if(mark[x]) return true;
mark[x] = true;
S[c++] = x;
for(int i = ; i < G[x].size(); i++){
if(!dfs(G[x][i])) return false;
}
return true;
}
void init(int n){
this->n = n;
for(int i = ; i < n * ; i++){
G[i].clear();
}
memset(mark, , sizeof(mark));
}
void add_clause(int x, int xval, int y, int yval){
x = x * + xval;
y = y * + yval;
G[x^].push_back(y);
G[y^].push_back(x);
}
bool solve(){
for(int i = ; i < n * ; i += ){
if(!mark[i] && !mark[i + ]){
c = ;
if(!dfs(i)){
while(c > ){
mark[S[--c]] = false;
}
if(!dfs(i + )){
return false;
}
}
}
}
return true;
}
};
Max-Flow(Dinic)
struct Dinic{
int n, m, i, s, t;
Edge e;
vector<Edge> edges;
vector<int> G[MAXN];
int d[MAXN], cur[MAXN];
bool vis[MAXN];
void init(int n){
this->n = n;
for (i = ; i <= n; i++){
G[i].clear();
}
edges.clear();
}
void AddEdge(int from, int to, int cap){
edges.push_back(Edge{ from, to, cap, });
edges.push_back(Edge{ to, from, , });
m = edges.size();
G[from].push_back(m - );
G[to].push_back(m - );
}
bool BFS(){
memset(vis, , sizeof(vis));
queue<int> Q;
Q.push(s);
d[s] = ;
vis[s] = ;
while (!Q.empty()){
int x = Q.front();
Q.pop();
for (i = ; i < G[x].size(); i++){
Edge& e = edges[G[x][i]];
if (!vis[e.to] && e.cap > e.flow){
vis[e.to] = true;
d[e.to] = d[x] + ;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x, int a){
if (x == t || a == ) return a;
int flow = , f;
for (int& i = cur[x]; i < G[x].size(); i++){
Edge& e = edges[G[x][i]];
if (d[x] + == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > ){
e.flow += f;
edges[G[x][i] ^ ].flow -= f;
flow += f;
a -= f;
if (a == ) break;
}
}
return flow;
}
int MaxFlow(int s, int t, int need){
int flow = ;
this->s = s;
this->t = t;
while (BFS()){
memset(cur, , sizeof(cur));
flow += DFS(s, INF);
if (flow > need) return flow;
}
return flow;
}
bool checkFull(int s){
for (int i = ; i < G[s].size(); i++){
if (edges[G[s][i]].flow != edges[G[s][i]].cap){
return false;
}
}
return true;
}
};
MCMF
struct Edge{
int u,v,c,cost,next;
}edge[E];
int head[V],cnt;
void init(){
cnt=;
memset(head,-,sizeof(head));
}
void addedge(int u,int v,int c,int cost)
{
edge[cnt].u=u;edge[cnt].v=v;edge[cnt].cost=cost;
edge[cnt].c=c;edge[cnt].next=head[u];head[u]=cnt++;
edge[cnt].u=v;edge[cnt].v=u;edge[cnt].cost=-cost;
edge[cnt].c=;edge[cnt].next=head[v];head[v]=cnt++;
}
bool spfa(int begin,int end){
int u,v;
queue<int> q;
for(int i=;i<=end+;i++){
pre[i]=-;
vis[i]=;
dist[i]=inf;
}
vis[begin]=;
dist[begin]=;
q.push(begin);
while(!q.empty()){
u=q.front();
q.pop();
vis[u]=;
for(int i=head[u];i!=-;i=edge[i].next){
if(edge[i].c>){
v=edge[i].v;
if(dist[v]>dist[u]+edge[i].cost){
dist[v]=dist[u]+edge[i].cost;
pre[v]=i;
if(!vis[v]){
vis[v]=true;
q.push(v);
}
}
}
}
}
return dist[end]!=inf;
}
int MCMF(int begin,int end){
int ans=,flow;
int flow_sum=;
while(spfa(begin,end)){
flow=inf;
for(int i=pre[end];i!=-;i=pre[edge[i].u])
if(edge[i].c<flow)
flow=edge[i].c;
for(int i=pre[end];i!=-;i=pre[edge[i].u]){
edge[i].c-=flow;
edge[i^].c+=flow;
}
ans+=dist[end];
flow_sum += flow;
}
//cout << flow_sum << endl;
return ans;
}
暑假集训-二分图,网络流,2-SAT的更多相关文章
- 2015UESTC 暑假集训总结
day1: 考微观经济学去了…… day2: 一开始就看了看一道题目最短的B题,拍了半小时交了上去wa了 感觉自己一定是自己想错了,于是去拍大家都过的A题,十分钟拍完交上去就A了 然后B题写了一发暴力 ...
- STL 入门 (17 暑假集训第一周)
快速全排列的函数 头文件<algorithm> next_permutation(a,a+n) ---------------------------------------------- ...
- 暑假集训Day2 互不侵犯(状压dp)
这又是个状压dp (大型自闭现场) 题目大意: 在N*N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. ...
- 暑假集训Day1 整数划分
题目大意: 如何把一个正整数N(N长度<20)划分为M(M>=1)个部分,使这M个部分的乘积最大.N.M从键盘输入,输出最大值及一种划分方式. 输入格式: 第一行一个正整数T(T<= ...
- [补档]暑假集训D5总结
%dalao 今天又有dalao来讲课,讲的是网络流 网络流--从入门到放弃:7-29dalao讲课笔记--https://hzoi-mafia.github.io/2017/07/29/27/ ...
- 「SDFZ听课笔记」二分图&&网络流
二分图? 不存在奇环(长度为奇数的环)的图 节点能黑白染色,使得不存在同色图相连的图 这两个定义是等价哒. 直观而言,就是这样的图: 二分图有一些神奇的性质,让一些在一般图上复杂度飞天的问题可以在正常 ...
- 二分图&网络流初步
链接 : 最小割&网络流应用 EK太低级了,不用. 那么请看:#6068. 「2017 山东一轮集训 Day4」棋盘,不用EK你试试? dinic模板及部分变形应用见zzz大佬的博客:网络流学 ...
- 二分图&网络流&最小割等问题的总结
二分图基础: 最大匹配:匈牙利算法 最小点覆盖=最大匹配 最小边覆盖=总节点数-最大匹配 最大独立集=点数-最大匹配 网络流: 技巧: 1.拆点为边,即一个点有限制,可将其转化为边 BZOJ1066, ...
- Uestc_suibian 暑假集训总结
唉,终于组队了,终于可以只BB了,我就BB,我就不上! 和Xiper以及chenxh组队了- 下面是总结: day1 第一天吃饱喝足,然后就上路了,我一开始就看到了C题大水题,但是我不敢想象这道题居然 ...
随机推荐
- 禁用cache
Z:\src\services\network\network_context.cc:http_cache_enabled
- Unity Shader (二)Cg语言
一.Cg基本数据类型 float 32位浮点数 half 16位浮点数 int 32位整型 fixed 12位定点数 bool 布尔数据 simpler* 纹理对象的句柄( the handle to ...
- 绿色版SecureCRT启动崩溃,遇到一个致命的错误且必须关闭
百度搜了半天,大家都是说删除注册表的VanDyke就能解决问题,但是我用的是绿色版的,删除VanDyke后还不行. 然后试了一下重新解压出一个绿色版的SecureCRT,发现能用. 但之前我配置了很多 ...
- p2p項目夭折,有種蛋蛋的憂傷。。
在高考完的暑假就在跟杰哥讨论怎样实现的校内p2p文件共享,就在今天.我们无奈的宣布差点儿夭折. 上图是測试图. 那时候的思路已经完好.就是:"学生上传共享文件到咱们工作室的server. ...
- how to backup and restore database of SQL Server
Back up 1,右键选中需要备份的数据库,Tasks-->Backup 2.General中,Destination,先remove掉之前的,然后再Add 需要注意的是,add的文件,必须要 ...
- spring IOC --- 控制反转(依赖注入)----简单的实例
IoC(Inversion of Control)控制反转,对象创建责任的反转,在spring中BeanFacotory是IoC容器的核心接口,负责实例化,定位,配置应用程序中的对象及建立这些对象间的 ...
- 99.重载[] * -> ->*
#include "mainwindow.h" #include <QApplication> #include <QPushButton>> //重 ...
- Noip 2016 Day1 题解
老师让我们刷历年真题, 然后漫不经心的说了一句:“你们就先做做noip2016 day1 吧” ...... 我还能说什么,,,,,老师你这是明摆着伤害我们啊2333333333 预计分数:100+2 ...
- 【基础篇】activity生命周期及数据保存
常见的Android 的界面,均采用Activity+view的形式显示的,一提到Activity,立即就能联想到Activity的生命周期与状态的保存. 下面先从Activity的生命周期开始说起 ...
- codeforces 710D Two Arithmetic Progressions(线性同余方程)
题目链接: http://codeforces.com/problemset/problem/710/D 分析:给你两个方程 a1k + b1 and a2l + b2,求在一个闭区间[L,R]中有多 ...