图论基础算法
dijkstral堆优化算法
struct node { int u,d; node(int u=0,int d=0):u(u),d(d){} bool operator < (const node& t) const{ return d>t.d; } }; struct edge { int u,v,w; edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){} }; vector<edge> G[maxn]; priority_queue<node> que; int N,D[maxn]; bool vis[maxn]; void Dijkstra(int s) { while(!que.empty()) que.pop(); for(int i=0;i<=N;i++) D[i]=INF; D[s]=0; memset(vis,false,sizeof(vis)); que.push(node(s,0)); while(!que.empty()) { node t=que.top(); que.pop(); int u=t.u; if(vis[u]) continue; vis[u]=true; int Size=G[u].size(); for(int i=0;i<Size;i++) { edge& e=G[u][i]; int v=e.v,w=e.w; if(D[v]>D[u]+w) { D[v]=D[u]+w; que.push(node(v,D[v])); } } } }
2SAT紫书模板
struct TwoSAT { int n; vector<int> G[maxn*2]; bool mark[maxn*2]; int S[maxn*2],c; bool dfs(int u) { if(mark[u^1]) return false; //对立面为真,矛盾 if(mark[u]) return true; mark[u]=true; S[c++]=u; //记录下来方便后面修改 int Size=G[u].size(); for(int i=0;i<Size;i++) { int v=G[u][i]; if(!dfs(v)) return false; } return true; } void init(int nn) { n=nn; for(int i=0;i<=2*n;i++) G[i].clear(),mark[i]=false; } void AddNode(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; } };
2SAT的Tarjan写法
struct TwoSAT { vector<int> G[2*maxn]; int dfn[2*maxn],low[2*maxn]; int KK[2*maxn],b[2*maxn]; bool vis[2*maxn]; int scc,top,id,n; void init(int nn=maxn-1) { n=nn; for(int i=0;i<=2*n;i++) { G[i].clear(); dfn[i]=0; vis[i]=false; } scc=top=id=0; } void AddEdge(int u,int d1,int v,int d2) { u=u*2+d1; v=v*2+d2; G[u].push_back(v); } void Tarjan(int u) { dfn[u]=low[u]=++id; vis[u]=true; KK[++top]=u; int v,Size=G[u].size(); for(int i=0;i<Size;i++) { v=G[u][i]; if(!dfn[v]) { Tarjan(v); low[u]=min(low[u],low[v]); } else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { scc++; while(true) { v=KK[top--]; vis[v]=false; b[v]=scc; if(v==u) break; } } } bool judge() { for(int i=0;i<2*n;i++) if(!dfn[i]) Tarjan(i); for(int i=0;i<2*n;i+=2) if(b[i]==b[i+1]) return false; return true; } }sat;
第K短路
#include<cstdio> #include<cstring> #include<string> #include<queue> #include<algorithm> using namespace std; const int INF=1e8; const int maxn=1001; int N,M,be,en,K; struct edge { int v,c,next; edge(int v=0,int c=0):v(v),c(c){} }E[2][maxn*100]; int head[2][maxn],eid; int dist[maxn]; int cnt[maxn]; struct node { int v,d; node(int v=0,int d=0):v(v),d(d){} bool operator < (const node& t) const { return d+dist[v]>t.d+dist[t.v]; } }; priority_queue<node> que; void Dij(int st) { memset(cnt,0,sizeof(cnt)); for(int i=0;i<=N;i++) dist[i]=INF; dist[st]=0; while(!que.empty()) que.pop(); que.push(node(st,0)); while(!que.empty()) { node t=que.top(); que.pop(); int u=t.v; if(cnt[u]) continue; cnt[u]=1; for(int i=head[1][u];i!=-1;i=E[1][i].next) { int v=E[1][i].v,c=E[1][i].c; if(dist[v]>dist[u]+c) { dist[v]=dist[u]+c; que.push(node(v,0)); } } } } int solve(int st) { memset(cnt,0,sizeof(cnt)); while(!que.empty()) que.pop(); que.push(node(st,0)); while(!que.empty()) { node t=que.top(); que.pop(); int u=t.v,d=t.d; cnt[u]++; if(cnt[u]==K) return d+dist[u]; for(int i=head[0][u];i!=-1;i=E[0][i].next) { int v=E[0][i].v,c=E[0][i].c; if(cnt[v]<=K) que.push(node(v,d+c)); } } return -1; } int main() { while(scanf("%d%d",&N,&M)!=EOF) { memset(head,-1,sizeof(head)); int u,v,c; eid=0; while(M--) { scanf("%d%d%d",&u,&v,&c); E[0][++eid]=edge(v,c); E[0][eid].next=head[0][u]; head[0][u]=eid; E[1][eid]=edge(u,c); E[1][eid].next=head[1][v]; head[1][v]=eid; } scanf("%d%d%d",&be,&en,&K); Dij(en); if(dist[be]==INF){ printf("-1\n"); continue; } if(be==en) K++; printf("%d\n",solve(be)); } return 0; }
最优比例生成树
#include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; const int maxn=105; const int maxm=10005; int N,M; double low,up,mid; struct edge { int u,v,w,c; edge(int u=0,int v=0,int w=0,int c=0) :u(u),v(v),w(w),c(c){} bool operator < (const edge& t) const { return (double)(w-mid*c)<(double)(t.w-mid*t.c); } }E[maxm]; int d[maxn]; int root(int a){ return d[a]==a?a:d[a]=root(d[a]); } double Kruskal() { sort(E,E+M); for(int i=0;i<=N;i++) d[i]=i; int step=0; double ret=0.0; for(int i=0;i<M;i++) { edge& e=E[i]; int u=e.u,v=e.v,w=e.w,c=e.c; int ra=root(u); int rb=root(v); if(ra==rb) continue; d[rb]=ra; ret+=(double)(w-mid*c); step++; if(step==N-1) break; } return ret; } double solve() { low=0,up=10000; int cnt=150; while(cnt--) { mid=(low+up)/2; if(Kruskal()>0) low=mid; else up=mid; } return low; } int main() { while(scanf("%d%d",&N,&M)!=EOF) { int u,v,w,c; for(int i=0;i<M;i++) { scanf("%d%d%d%d",&u,&v,&w,&c); E[i]=edge(u,v,w,c); } printf("%.4f\n",solve()); } return 0; }
Prim算法
int prim(int st) { for(int i=0;i<maxn;i++) D[i]=INF; D[st]=0; memset(vis,false,sizeof(vis)); int ret=0; for(int i=0;i<N;i++) { int pos=-1; for(int j=0;j<N;j++) if(!vis[j]&&(pos==-1||D[j]<D[pos])) pos=j; if(pos==-1) break; vis[pos]=true; ret+=D[pos]; for(int j=0;j<N;j++) D[j]=min(D[j],dist[pos][j]); } return ret; }
Bellman算法
int dist[155]; bool bellman() { memset(dist,0,sizeof(dist)); for(int i=1;i<=N;i++) for(int j=0;j<M;j++) { edge& e=save[j]; if(dist[e.to]>dist[e.from]+e.weight) dist[e.to]=dist[e.from]+e.weight; } for(int j=0;j<M;j++) { { edge& e=save[j]; if(dist[e.to]>dist[e.from]+e.weight) return false; } } return true; }
Dijkstra算法
int dist[35][35],vis[35],D[35]; int dijkstra(int op) { memset(vis,0,sizeof(vis)); for(int i=1;i<=N;i++) D[i]=INF; vis[op]=1; D[1]=0; while(true) { int pos=-1; for(int i=1;i<=N;i++) if(!vis[i]&&(pos==-1||D[i]<D[pos])) pos=i; if(pos==-1) break; vis[pos]=1; for(int i=1;i<=N;i++) D[i]=min(D[i],D[pos]+dist[i][pos]); } return D[N]; }
spfa算法
double D[105]; bool inq[105]; bool spfa(int start) { for(int i=1;i<=N;i++) D[i]=dbinf; memset(inq,false,sizeof(inq)); D[start]=0.0; queue<int> que; que.push(start); while(!que.empty()) { int now=que.front(); que.pop(); inq[now]=false; for(int i=1;i<=N;i++) if(i!=now&&dist[i][now]<=10.0&&D[i]>D[now]+dist[i][now]) { D[i]=D[now]+dist[i][now]; if(!inq[i]) { inq[i]=true; que.push(i); } } } for(int i=1;i<=N;i++) { if(D[i]>10000000.0) return false; ans=max(ans,D[i]); } return true; }