匈牙利算法DFS
bool dfs(int u){ for(int i = 1; i <= n; i++){ if(a[u][i] && !visit[i]){ visit[i] = true; if(match[i] == -1 || 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 = 1; i <= n; i++){ if(y[i]) continue; int p = fx[u] + fy[i] - a[u][i]; if(p == 0){ y[i] = true; if(match[i] == -1 || dfs(match[i])){ match[i] = u; return true; } }else{ m = min(m, p); } } return false; } void KM(){ int i,j; memset(fx,0,sizeof(fx)); memset(fy,0,sizeof(fy)); memset(match,-1,sizeof(match)); for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ if(a[i][j] > fx[i]){ fx[i] = a[i][j]; } } } for(int i = 1; i <= n; i++){ while(true){ memset(x, 0, sizeof(x)); memset(y, 0, sizeof(y)); m = INF; if(dfs(i)) break; for(int j = 1; 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, 0, sizeof(a)); for(int i = 1; i <= n; i++){ scanf("%s", s[i]); } for(int i = 1; i <= n; i++){ int p = strlen(s[i]); for(int j = 1; j <= n; j++){ if(i == j) continue; int q = strlen(s[j]) - 1; int cnt = 0; while(cnt < p && q >= 0 && s[i][cnt] == s[j][q]){ cnt++; q--; } a[i][j] = cnt; } } KM(); int ans = 0; for(int i = 1; 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*2]; bool mark[MAXN*2]; int S[MAXN*2], c; bool dfs(int x){ if(mark[x^1]) return false; if(mark[x]) return true; mark[x] = true; S[c++] = x; for(int i = 0; i < G[x].size(); i++){ if(!dfs(G[x][i])) return false; } return true; } void init(int n){ this->n = n; for(int i = 0; i < n * 2; i++){ G[i].clear(); } memset(mark, 0, sizeof(mark)); } void add_clause(int x, int xval, int y, int yval){ x = x * 2 + xval; y = y * 2 + yval; G[x^1].push_back(y); G[y^1].push_back(x); } bool solve(){ for(int i = 0; i < n * 2; i += 2){ if(!mark[i] && !mark[i + 1]){ c = 0; if(!dfs(i)){ while(c > 0){ mark[S[--c]] = false; } if(!dfs(i + 1)){ 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 = 0; i <= n; i++){ G[i].clear(); } edges.clear(); } void AddEdge(int from, int to, int cap){ edges.push_back(Edge{ from, to, cap, 0 }); edges.push_back(Edge{ to, from, 0, 0 }); m = edges.size(); G[from].push_back(m - 2); G[to].push_back(m - 1); } bool BFS(){ memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(s); d[s] = 0; vis[s] = 1; while (!Q.empty()){ int x = Q.front(); Q.pop(); for (i = 0; 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] + 1; Q.push(e.to); } } } return vis[t]; } int DFS(int x, int a){ if (x == t || a == 0) return a; int flow = 0, f; for (int& i = cur[x]; i < G[x].size(); i++){ Edge& e = edges[G[x][i]]; if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0){ e.flow += f; edges[G[x][i] ^ 1].flow -= f; flow += f; a -= f; if (a == 0) break; } } return flow; } int MaxFlow(int s, int t, int need){ int flow = 0; this->s = s; this->t = t; while (BFS()){ memset(cur, 0, sizeof(cur)); flow += DFS(s, INF); if (flow > need) return flow; } return flow; } bool checkFull(int s){ for (int i = 0; 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=0; memset(head,-1,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=0;edge[cnt].next=head[v];head[v]=cnt++; } bool spfa(int begin,int end){ int u,v; queue<int> q; for(int i=0;i<=end+2;i++){ pre[i]=-1; vis[i]=0; dist[i]=inf; } vis[begin]=1; dist[begin]=0; q.push(begin); while(!q.empty()){ u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i!=-1;i=edge[i].next){ if(edge[i].c>0){ 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=0,flow; int flow_sum=0; while(spfa(begin,end)){ flow=inf; for(int i=pre[end];i!=-1;i=pre[edge[i].u]) if(edge[i].c<flow) flow=edge[i].c; for(int i=pre[end];i!=-1;i=pre[edge[i].u]){ edge[i].c-=flow; edge[i^1].c+=flow; } ans+=dist[end]; flow_sum += flow; } //cout << flow_sum << endl; return ans; }