1.Prim
void prim()
{
int i,j,k,min;
for(i=2;i<=n;i++)
dis[i]=map[1][i];
vis[1]=1;
for(i=2;i<=n;i++)//經過N次遍歷一定能遍歷所有的點 也就是完成了最終目標.
{
min=inf;
for(j=1;j<=n;j++)
{
if(vis[j]==0 &&dis[j]<min)
{
min=dis[j];
k=j;
}
}
if(min==inf)
break;
vis[k]=1;
sum+=sqrt(1.0*min);//完成了一次權值加和.
for(j=2;j<=n;j++)
{
if(vis[j]==0 &&dis[j]>map[k][j])
dis[j]=map[k][j];
}//更新最優解.
}
}
2.二分匹配
int find(int x)
{
for(int i=1;i<=m;i++)
{
if(vis[i]==0&&map[i][x])
{
vis[i]=1;
if(pri[i]==-1||find(pri[i]))
{
pri[i]=x;
return 1;
}
}
}
return 0;
}
3.Bellman
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
int dis[121212];
int u[121212];
int v[121212];
int w[121212];
int main()
{
int n,m;
int check;
while(~scanf("%d%d",&n,&m))
{
if(n==0||m==0)break;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u[i],&v[i],&w[i]);
}
for(int i=1;i<=n;i++)
{
dis[i]=0x1f1f1f1f;
}
dis[1]=0;
for(int k=1;k<=n-1;k++)//最多遍歷點的次數.
{
check=0;
for(int i=1;i<=m;i++)
{
if(dis[v[i]]>dis[u[i]]+w[i])
{
dis[v[i]]=dis[u[i]]+w[i];
check=1;
}
if(dis[u[i]]>dis[v[i]]+w[i])
{
dis[u[i]]=dis[v[i]]+w[i];
check=1;
}
}
if(check==0)break;
}
int flag=0;//標記是否有負權迴路...
for(int i=0;i<=m;i++)
{
if(dis[v[i]]>dis[u[i]]+w[i])
{
dis[v[i]]=dis[u[i]]+w[i];
flag=1;
}
if(dis[u[i]]>dis[v[i]]+w[i])
{
dis[u[i]]=dis[v[i]]+w[i];
flag=1;
}
}
if(flag==1){printf("0\n");continue;}
printf("%d\n",dis[n]);
}
}
4.Dij
void dijkstra(int s)
{
d[s]=0;
for(int k=0;k<n;k++)
{
int m=INF;
for(int i=0;i<n;i++)
{
if(!vis[i] && d[i]<=m)
m=d[s=i];
}
vis[s] = 1;
for(int i=0;i<n;i++)
{
d[i]=MIN(d[i],d[s]+w[s][i]);
}
}
}
void Dij()
{
int i,j,k,v,tmp;
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++)//這裏等號很魔怔
d[i]=w[1][i];//當然是要起點開始走.
d[1]=0;
vis[1]=1;
for(i=1;i<=n;i++)//爲了連接多少點的控制.//這裏等號一樣魔怔
{
tmp=N;
for(j=1;j<=n;j++)
{
if(tmp>d[j]&&!vis[j])
{
tmp=d[j];
v=j;
}
}//每次選中的都是距離起點最近的點.v
vis[v]=1;
for(k=1;k<=n;k++)
{
if(!vis[k])//然後鬆弛.
d[k]=min(d[k],d[v]+w[v][k]);
}
}
}
#include<stdio.h>
#include<string.h>
#include<map>
#include<iostream>
#include<vector>
#include<queue>
const int maxn=30003;
const int INF=0x1f1f1f1f;
int n,m;
using namespace std;
struct Edge
{
int from,to,dist;
Edge(int u,int v,int d):from(u),to(v),dist(d) {}
};
string s;
string e;
vector<Edge>edges;//存儲邊的結點信息
vector<int>G[maxn];//鄰接表
bool done[maxn]; //標記是否訪問過
int d[maxn]; //距離數組
map<string,int>cnt;//映射成節點編號
struct heapnode //用於優先隊列自定義
{
int d,u;
bool operator <(const heapnode rhs) const
{
return d > rhs.d;
}
heapnode(int dd,int uu):d(dd),u(uu) {}
};
void init()//初始化必不可少
{
for(int i=0; i<n; i++)
G[i].clear();
edges.clear();
}
void dij( int s)
{
priority_queue<heapnode>Q;
for(int i=0; i<=n; i++)//初始化距離數組
d[i]=INF;
d[s]=0;
memset(done ,0,sizeof(done));
Q.push( heapnode(0,s) );
while(!Q.empty())
{
heapnode x = Q.top();
Q.pop();
int u=x.u;
if(u==cnt[e])
{
printf("%d\n",x.d);
break;
}
if(done[u])continue;
done[u] = true;
for(int i=0; i<G[u].size(); i++)
{
Edge& e=edges[G[u][i]];//取出來一條鄰接邊
if(d[e.to]>d[u]+e.dist)
{
d[e.to] = d[u] + e.dist;
Q.push((heapnode(d[e.to],e.to)));
}
}
}
}
void addedge(int from,int to,int dist)
{
edges.push_back(Edge(from,to,dist));
int m = edges.size();
G[from].push_back(m-1);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
int t=1;
int ans=0;
string str;
init();
for(int i=0; i<n; i++)
{
cin>>str;
cnt[str]=t++;
}
for(int i=0; i<m; i++)
{
string str2;
int x;
cin>>str>>str2>>x;
addedge(cnt[str],cnt[str2],x);
addedge(cnt[str2],cnt[str],x);
}
cin>>s>>e;
dij(cnt[s]);
s.clear();
e.clear();
cnt.clear();
}
return 0;
}
4.Floyd最小環
int ans=0x1f1f1f1f;
for(int i=0; i<n; i++)
{
for(int j=0; j<i; j++)
{
for(int k=j+1; k<i; k++)
{
ans=min(ans,map[j][k]+dis[k][i]+dis[i][j]);
}
}
for(int j=0; j<n; j++)
{
for(int k=0; k<n; k++)
{
map[j][k]=min(map[j][k],map[j][i]+map[i][k]);
}
}
}
5.SPFA
int SPFA(int s)
{
int i;
bool visit[N] = {false};
int front = 0, rear = 1;
memset(queue,0,sizeof(queue));
for(i=1;i<=n;i++)
d[i] = MAX;
queue[front] = s;
visit[s] = true;
d[s] = 0;
while(front<rear)
{
int u = queue[front];
visit[u] = false;
for(int i=1; i<=n; i++)
{
if (d[i]>d[u]+ edges[u][i])
{
d[i]= d[u]+edges[u][i];
if( !visit[i] )
{
visit[i] = true;
queue[rear++] = i;
}
}
}
front++;
}
return 0;
}
6.最小樹形圖
#define INF 0x7fffffff
double x[1000];
double y[1000];
double w[1000][1000];
int flag[1000];//判斷是否在有向環裏邊的縮點
int vis[1000];
int pre[1000];
int n,m;
void init()//不能少了初始化的內容
{
memset(vis, 0, sizeof(vis));
memset(flag, 0, sizeof(flag));
for(int i=0; i<=n; i++)
{
w[i][i] = INF;
for(int j=i+1; j<=n; j++)
w[i][j]=w[j][i]=INF;
}
}
double directed_mst(int u)//u表示根節點
{
double ans=0;
memset(vis, 0, sizeof(vis));
while(true)
{
//求最短弧集合E
for(int i=1; i<=n; i++)if(i!=u&&!flag[i])
{
w[i][i]=INF, pre[i] = i;
for(int j=1; j<=n; j++)if(!flag[j] && w[j][i]<w[pre[i]][i])
{
pre[i] = j;
}
if(pre[i]==i)return -1;//也可以用dfs預處理判斷凸的連通
}
//判斷E是否有環
int i;
for(i=1; i<=n; i++)
{
if(i!=u&&!flag[i])
{
int j=i, cnt=0;
while(j!=u && pre[j]!=i && cnt<=n) j=pre[j], ++cnt;
if(j==u || cnt>n) continue; //最後能找到起點(根)或者是走過的點已經超過了n個,表示沒有有向環
break;
}
}
if(i>n)
{
for(int i=1; i<=n; i++)if(i!=u && !flag[i]) ans+=w[pre[i]][i];
return ans;
}
//有環,進行收縮,把整個環都收縮到一個點i上。
int j=i;
memset(vis, 0, sizeof(vis));
do
{
ans += w[pre[j]][j], j=pre[j], vis[j]=flag[j]=true;//對環內的點標記,並且直接對環的權值進行加和記錄,在最後找到最小樹形圖之後就不用展開收縮點了
}
while(j!=i);
flag[i] = false; // 環縮成了點i,點i仍然存在
//收縮點的同時,對邊權值進行改變
for(int k=1; k<=n; ++k)if(vis[k]) // 在環中點點
{
for(int j=1; j<=n; j++)if(!vis[j]) // 不在環中的點
{
if(w[i][j] > w[k][j]) w[i][j] = w[k][j];
if(w[j][k]<INF && w[j][k]-w[pre[k]][k] < w[j][i])
w[j][i] = w[j][k] - w[pre[k]][k];
}
}
}
return ans;
}
7.LCA
①離線Tarjan
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
int head[100000];
int f[100000];
int qhead[100000];
int vis[100000];
int dir[100000];
int problem[100000][2];
struct EdgeNode
{
int from;
int to;
int w;
int lca;
int next;
}e[100000],q[100000];
int n,m,ask,cont;
int find(int a)
{
int r=a;
while(f[r]!=r)
r=f[r];
int i=a;
int j;
while(i!=r)
{
j=f[i];
f[i]=r;
i=j;
}
return r;
}
void merge(int a,int b)
{
int A,B;
A=find(a);
B=find(b);
if(A!=B)
f[B]=A;
}
void add(int from,int to,int w)
{
e[cont].from=from;
e[cont].to=to;
e[cont].w=w;
e[cont].next=head[from];
head[from]=cont;
cont++;
e[cont].from=to;
e[cont].to=from;
e[cont].w=w;
e[cont].next=head[to];
head[to]=cont;
cont++;
}
void addq(int from,int to)
{
q[cont].from=from;
q[cont].to=to;
q[cont].lca=-1;
q[cont].next=qhead[from];
qhead[from]=cont;
cont++;
q[cont].from=to;
q[cont].to=from;
q[cont].lca=-1;
q[cont].next=qhead[to];
qhead[to]=cont;
cont++;
}
void LCA(int u)
{
f[u]=u;
vis[u]=1;
for(int k=head[u];k!=-1;k=e[k].next)
{
int to=e[k].to;
if(vis[to]==0)
{
int w=e[k].w;
dir[to]=dir[u]+w;
LCA(to);
merge(u,to);
}
}
for(int k=qhead[u];k!=-1;k=q[k].next)
{
int to=q[k].to;
if(vis[to]==1)
{
q[k].lca=find(to);
q[k^1].lca=q[k].lca;
}
}
}
8.Kosaraju
#include<stdio.h>
#include<string.h>
using namespace std;
int head[100000];
int head2[100000];
struct EdgeNode
{
int from;
int to;
int next;
}e[100000],ee[100000];
int n,m,cont,cont2,sig;
int degree[1000000];
int vis[1000000];
int num[1000000];
int color[1000000];
void add(int from,int to)
{
e[cont].from=from;
e[cont].to=to;
e[cont].next=head[from];
head[from]=cont++;
}
void add2(int from,int to)
{
ee[cont2].from=from;
ee[cont2].to=to;
ee[cont2].next=head2[from];
head2[from]=cont2++;
}
void Dfs(int u)
{
vis[u]=1;
for(int k=head[u];k!=-1;k=e[k].next)
{
int v=e[k].to;
if(vis[v]==0)
{
Dfs(v);
}
}
num[sig++]=u;
}
void Dfs2(int u)
{
vis[u]=1;
color[u]=sig;
for(int k=head2[u];k!=-1;k=ee[k].next)
{
int v=ee[k].to;
if(vis[v]==0)
{
Dfs2(v);
}
}
}
void Kosaraju()
{
sig=1;
memset(color,0,sizeof(color));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
if(vis[i]==0)
{
Dfs(i);
}
}
sig=0;
memset(vis,0,sizeof(vis));
for(int i=n;i>=1;i--)
{
if(vis[num[i]]==0)
{
sig++;
Dfs2(num[i]);
}
}
for(int i=1;i<=n;i++)
{
for(int k=head[i];k!=-1;k=e[k].next)
{
int vv=e[k].to;
if(color[vv]!=color[i])
{
degree[color[i]]++;
}
}
}
int tot=0;
int tmp=-1;
for(int i=1;i<=sig;i++)
{
if(degree[i]==0)
{
tot++;
tmp=i;
}
}
if(tot==1)
{
int output=0;
for(int i=1;i<=n;i++)
{
if(color[i]==tmp)output++;
}
printf("%d\n",output);
}
else printf("0\n");
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
cont=0;cont2=0;
memset(num,0,sizeof(num));
memset(degree,0,sizeof(degree));
memset(vis,0,sizeof(vis));
memset(color,0,sizeof(color));
memset(head,-1,sizeof(head));
memset(head2,-1,sizeof(head2));
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add2(y,x);
}
Kosaraju();
}
}
9.強連通Tarjan
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
vector<int >mp[1000000];
int stack[1000000];
int vis[1000000];
int low[1000000];
int color[1000000];
int dfn[1000000];
int n,m,cnt,sig,tt;
void Tarjan(int u)
{
vis[u]=1;
low[u]=dfn[u]=cnt++;
stack[++tt]=u;
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(vis[v]==0)
{
Tarjan(v);
}
if(vis[v]==1)low[u]=min(low[u],low[v]);
}
if(dfn[u]==low[u])
{
sig++;
do
{
color[stack[tt]]=sig;
low[stack[tt]]=sig;
vis[stack[tt]]=2;
}while(stack[tt--]!=u);
}
}
void Slove()
{
cnt=1;
sig=0;tt=-1;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
if(vis[i]==0)
{
Tarjan(i);
}
}
if(sig==1)
{
printf("Yes\n");
}
else printf("No\n");
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)break;
for(int i=1;i<=n;i++)mp[i].clear();
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
mp[x].push_back(y);
}
Slove();
}
}
10.Tarjan求割點
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int head[100000];
int dfn[100000];
int low[100000];
int ans[100000];
struct EdgeNode
{
int to;
int w;
int next;
}e[100000];
int cont,cnt,root;
void add(int from,int to)
{
e[cont].to=to;
e[cont].next=head[from];
head[from]=cont++;
}
void init()
{
cont=0;
cnt=1;
root=1;
memset(head,-1,sizeof(head));
memset(ans,0,sizeof(ans));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
}
// 樹邊 low[u]=min(low[u],low[v]);
// 回邊 low[u]=min(low[u],dfn[v]);
void Tarjan(int u,int from)
{
int son=0;
dfn[u]=low[u]=cnt;
cnt++;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(dfn[v]==0)
{
Tarjan(v,u);
low[u]=min(low[u],low[v]);
if(u==root)
{
son++;
if(son>1)ans[u]=1;
}
if(low[v]>=dfn[u]&&u!=root)
{
ans[u]=1;
}
}
else if(from!=v)low[u]=min(low[u],dfn[v]);
}
}
11.FF最大流
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
int map[350][350];
int pre[350];
int vis[350];
int m,n,maxflow;
int s,t;
int Bfs(int ss,int tt)
{
memset(vis,0,sizeof(vis));
memset(pre,0,sizeof(pre));
queue<int >s;
s.push(ss);
vis[ss]=1;
while(!s.empty())
{
int u=s.front();
if(u==tt)return 1;
s.pop();
for(int v=1;v<=n;v++)
{
if(vis[v]==0&&map[u][v]!=0)
{
vis[v]=1;
pre[v]=u;
s.push(v);
}
}
}
return 0;
}
void Ford_Fulkerson()
{
maxflow=0;
while(1)
{
if(Bfs(s,t)==1)
{
int Min=0x3f3f3f3f;
for(int i=t;i!=s;i=pre[i])
{
Min=min(Min,map[pre[i]][i]);
}
for(int i=t;i!=s;i=pre[i])
{
map[pre[i]][i]-=Min;
map[i][pre[i]]+=Min;
}
maxflow+=Min;
}
else break;
}
printf("%d\n",maxflow);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
s=1;t=n;
memset(map,0,sizeof(map));
for(int i=1;i<=m;i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
map[x][y]+=w;
}
Ford_Fulkerson();
}
}
12.EK最大流
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
int head[2550];
struct node
{
int from,to,w,next;
}e[2550*2550];
int vis[2550];
int pre[255000];
int n,m,s,t,sum,cont;
void add(int from,int to,int w)
{
e[cont].from=from;
e[cont].to=to;
e[cont].w=w;
e[cont].next=head[from];
head[from]=cont++;
e[cont].from=to;
e[cont].to=from;
e[cont].w=0;
e[cont].next=head[to];
head[to]=cont++;
}
int Ek_Bfs(int start,int end)
{
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
vis[start]=1;
queue<int >s;
s.push(start);
while(!s.empty())
{
int u=s.front();
if(u==end)return 1;
s.pop();
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(vis[v]==0&&e[i].w>0)
{
vis[v]=1;
pre[v]=i;
s.push(v);
}
}
}
return 0;
}
void Edmond_Karp()
{
int maxflow=0;
int minn;
while(Ek_Bfs(s,t))
{
minn=0x3f3f3f3f;
int u=t;
while(u!=s)
{
minn=min(e[pre[u]].w,minn);
u=e[pre[u]].from;
}
u=t;
while(pre[u]!=-1)
{
e[pre[u]].w-=minn;
e[pre[u]^1].w+=minn;
u=e[pre[u]].from;
}
maxflow+=minn;
}
}
13.Dinic
int makedivv()
{
memset(divv,0,sizeof(divv));
divv[ss]=1;
queue<int >s;
s.push(ss);
while(!s.empty())
{
int u=s.front();
if(u==tt)return 1;
s.pop();
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if(w&&divv[v]==0)
{
divv[v]=divv[u]+1;
s.push(v);
}
}
}
return 0;
}
int Dfs(int u,int maxflow,int tt)
{
if(tt==u)return maxflow;
int ret=0;
for(int &i=cur[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if(w&&divv[v]==divv[u]+1)
{
int f=Dfs(v,min(maxflow-ret,w),tt);
e[i].w-=f;
e[i^1].w+=f;
ret+=f;
if(ret==maxflow)return ret;
}
}
return ret;
}
int Dinic()
{
int ans=0;
while(makedivv()==1)
{
memcpy(cur,head,sizeof(head));
ans+=Dfs(ss,INF,tt);
}
return ans;
}
14.費用流
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct node
{
int from;
int to;
int w;
int f;
int next;
int num;
}e[15151515];
int n,m,ss,tt,cont;
int path[151515];
int pre[151515];
int head[151515];
int dis[151515];
int vis[151515];
void add(int from,int to,int w,int f)
{
e[cont].from=from;
e[cont].to=to;
e[cont].f=f;
e[cont].w=w;
e[cont].num=cont;
e[cont].next=head[from];
head[from]=cont++;
}
int SPFA()
{
queue<int >s;
s.push(ss);
memset(pre,-1,sizeof(pre));
memset(path,-1,sizeof(path));
for(int i=1;i<=tt;i++)dis[i]=0x3f3f3f3f;
dis[ss]=0;
memset(vis,0,sizeof(vis));
vis[ss]=1;
while(!s.empty())
{
int u=s.front();
s.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
int f=e[i].f;
if(f&&dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
pre[v]=u;
path[v]=e[i].num;
if(vis[v]==0)
{
s.push(v);
vis[v]=1;
}
}
}
}
if(dis[tt]!=0x3f3f3f3f)return 1;
else return 0;
}
void Min_costflow()
{
int ans=0;
int maxflow=0;
while(SPFA()==1)
{
int minn=0x3f3f3f3f;
for(int i=tt;i!=ss;i=pre[i])
{
minn=min(minn,e[path[i]].f);
}
maxflow+=minn;
ans+=dis[tt]*minn;
for(int i=tt;i!=ss;i=pre[i])
{
e[path[i]].f-=minn;
e[path[i]^1].f+=minn;
}
}
printf("%d\n",ans);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
ss=n+1;
tt=ss+1;
cont=0;
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
add(x,y,w,1);
add(y,x,-w,0);
add(y,x,w,1);
add(x,y,-w,0);
}
add(ss,1,0,2);
add(1,ss,0,0);
add(n,tt,0,2);
add(tt,n,0,0);
Min_costflow();
}
}
15.Km最優二分匹配
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
int a[500][500];
int visx[500];
int visy[500];
int lx[500];
int ly[500];
int match[500];
int n;
int low;
int find(int u)
{
visx[u]=1;
for(int i=1;i<=n;i++)
{
if(visy[i]==1)continue;
int tmp=lx[u]+ly[i]-a[u][i];
if(tmp==0)
{
visy[i]=1;
if(match[i]==-1||find(match[i]))
{
match[i]=u;
return 1;
}
}
else if(low>tmp)low=tmp;
}
return 0;
}
void KM()
{
memset(match,-1,sizeof(match));
memset(lx,0,sizeof(lx));
memset(ly,0,sizeof(ly));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
lx[i]=max(lx[i],a[i][j]);
}
}
for(int i=1;i<=n;i++)
{
while(1)
{
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
low=INF;
if(find(i))break;
for(int i=1;i<=n;i++)
{
if(visx[i])lx[i]-=low;
if(visy[i])ly[i]+=low;
}
}
}
int sum=0;
for(int i=1;i<=n;i++)
{
sum+=a[match[i]][i];
}
printf("%d\n",sum);
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
}
}
KM();
}
}
16.點雙聯通
void Tarjan(int u,int from)
{
vis[u]=1;
dfn[u]=low[u]=cnt++;
stack[++tot]=u;
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(v==from)continue;
if(vis[v]==0)
{
Tarjan(v,u);
low[u]=min(low[u],low[v]);
}
else low[u]=min(low[u],low[v]);
}
if(low[u]==dfn[u])
{
sig++;
do
{
color[stack[tot]]=sig;
vis[stack[tot]]=-1;
}
while(stack[tot--]!=u);
}
}
17.邊雙連通
void Tarjan(int u,int from)
{
vis[u]=1;
dfn[u]=low[u]=cnt++;
stack[++tt]=u;
int flag=0;
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(vis[v]==0)
{
Tarjan(v,u);
low[u]=min(low[u],low[v]);
}
else if(v==from)
{
if(flag)low[u]=min(low[u],dfn[v]);
flag++;
}
else low[u]=min(low[u],low[v]);
}
if(low[u]==dfn[u])
{
sig++;
do
{
color[stack[tt]]=sig;
vis[stack[tt]]=-1;
}
while(stack[tt--]!=u);
}
}
18.Floyd最小環+輸出路徑
#include<stdio.h>
#include<string.h>
using namespace std;
int map[105][105];
int dis[105][105];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
dis[i][j]=map[i][j]=99999999;
}
}
for(int i=0;i<m;i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
if(map[x][y]>w)
{
map[x][y]=map[y][x]=w;
dis[x][y]=dis[y][x]=w;
}
}
int ans=0;
int output=99999999;
for(int i=1;i<=n;i++)
{
for(int j=1;j<i;j++)//
{
for(int k=j+1;k<i;k++)
{
if(dis[j][k]+map[k][i]+map[i][j]<output)
{
output=dis[j][k]+map[k][i]+map[i][j];
ans=1;
}
else if(dis[j][k]+map[k][i]+map[i][j]==output)
{
ans++;
}
}
}
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
if(dis[j][k]>dis[j][i]+dis[i][k])
{
dis[j][k]=dis[j][i]+dis[i][k];
}
}
}
}
printf("%d %d\n",output,ans);
}
}
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<map>
#include<stack>
using namespace std;
map<string,int >s;
map<int,string>re;
int n;
int path[605][605];
int mp[605][605];
int dist[605][605];
void add(int u,int v)
{
mp[u][v]=dist[u][v]=1;
}
void init()
{
memset(path,0,sizeof(path));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
mp[i][j]=dist[i][j]=0x3f3f3f3f;
}
}
}
void getPath(int i ,int j){
if(i==j) return;
if(path[i][j]==0) cout<<re[j]<<" ";
else{
getPath(i,path[i][j]);
getPath(path[i][j],j);
}
}
void Slove()
{
int x,y,z;
int minn=0x3f3f3f3f;
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dist[i][j]!=0x3f3f3f3f&&mp[j][k]!=0x3f3f3f3f&&mp[k][i]!=0x3f3f3f3f)
{
if(dist[i][j]+mp[j][k]+mp[k][i]<minn)
{
x=i,y=j,z=k;
minn=dist[i][j]+mp[j][k]+mp[k][i];
}
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dist[i][k]!=0x3f3f3f3f&&dist[k][j]!=0x3f3f3f3f)
{
if(dist[i][k]+dist[k][j]<dist[i][j])
{
dist[i][j]=dist[i][k]+dist[k][j];
path[i][j]=k;
}
}
}
}
}
for(int i=1;i<=n;i++)
{
if(mp[i][i]==1)
{
cout<<re[i]<<endl;
return ;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(mp[i][j]==1&&mp[j][i]==1)
{
cout<<re[i]<<" "<<re[j]<<" "<<endl;
return ;
}
}
}
if(minn==0x3f3f3f3f)printf("SHIP IT\n");
else
{
cout<<re[x]<<" ";
getPath(x,y);
cout<<re[z]<<endl;
}
}
int main()
{
while(~scanf("%d",&n))
{
init();
int cnt=0;
for(int i=1;i<=n;i++)
{
char temp[100000];scanf("%s",temp);
s[temp]=++cnt;
re[cnt]=temp;
}
for(int i=1;i<=n;i++)
{
char temp[100000];scanf("%s",temp);
char sss[100000];
int u=s[temp];
int d;scanf("%d",&d);
getchar();
for(int j=0;j<d;j++)
{
int l=0;
int flag=0;
gets(temp);
int len=strlen(temp);
for(int j=0;j<len;j++)
{
if(temp[j]==' ')
{
flag=1;
continue;
}
if(temp[j]==','||j==len-1)
{
if(j==len-1)sss[l++]=temp[j];
flag=0;
sss[l]='\0';
int v=s[sss];
l=0;
add(u,v);
continue;
}
if(flag==1)
{
sss[l++]=temp[j];
}
}
}
}
Slove();
}
}
19.2-sat輸出可行解
//LightOJ 1251
#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
int output[40005];
int vis[70005];
int low[70005];
int dfn[70005];
int print[70005];
int stack[70005];
int color[70005];
int pos[70005];
int degree[70005];
vector<int >mp[70005];
vector<int >mp2[70005];
int n,m,sig,cnt,tot,cont;
void add(int x,int y)
{
mp[x].push_back(y);
}
void top()
{
memset(print,0,sizeof(print));
queue<int >s;
for(int i=1;i<=sig;i++)
{
if(degree[i]==0)
{
s.push(i);
}
}
while(!s.empty())
{
int u=s.front();
if(print[u]==0)
{
print[u]=1;print[pos[u]]=2;
}
s.pop();
for(int i=0;i<mp2[u].size();i++)
{
int v=mp2[u][i];
degree[v]--;
if(degree[v]==0)s.push(v);
}
}
cont=0;
for(int i=1;i<=n;i++)if(print[color[i]]==1)output[cont++]=i;
}
void Tarjan(int u)
{
vis[u]=1;
dfn[u]=low[u]=cnt++;
stack[++tot]=u;
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(vis[v]==0)Tarjan(v);
if(vis[v]==1)low[u]=min(low[u],low[v]);
}
if(low[u]==dfn[u])
{
sig++;
do
{
vis[stack[tot]]=-1;
color[stack[tot]]=sig;
}
while(stack[tot--]!=u);
}
}
int Slove()
{
sig=0;
cnt=1;
tot=-1;
memset(degree,0,sizeof(degree));
memset(stack,0,sizeof(stack));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(vis,0,sizeof(vis));
memset(color,0,sizeof(color));
for(int i=1;i<=n*2;i++)
{
if(vis[i]==0)
{
Tarjan(i);
}
}
for(int i=1;i<=n;i++)
{
if(color[i]==color[i+n])return 0;
pos[color[i]]=color[i+n];
pos[color[i+n]]=color[i];
}
for(int i=1;i<=n*2;i++)
{
for(int j=0;j<mp[i].size();j++)
{
int v=mp[i][j];
if(color[i]!=color[v])
{
degree[color[i]]++;
mp2[color[v]].push_back(color[i]);
}
}
}
top();
return 1;
}
int main()
{
int t;
int kase=0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&m,&n);
for(int i=1;i<=60000;i++)mp[i].clear(),mp2[i].clear();
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
int xx=x;int yy=y;
if(x<0)x=-x;
if(y<0)y=-y;
if(xx>0&&yy>0)add(x+n,y),add(y+n,x);
if(xx>0&&yy<0)add(x+n,y+n),add(y,x);
if(xx<0&&yy>0)add(x,y),add(y+n,x+n);
if(xx<0&&yy<0)add(x,y+n),add(y,x+n);
}
int ans=Slove();
printf("Case %d: ",++kase);
if(ans==1)
{
printf("Yes\n");
printf("%d",cont);
for(int i=0;i<cont;i++)
{
printf(" %d",output[i]);
}
printf("\n");
}
else printf("No\n");
}
}