一些图论模板
1.单源最短路
//Twenty
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int n,m,maxl=1e9,x,y,s,t,vis[110];
double a[110],b[110],f[110][110],dis[110];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
cin>>a[i]>>b[i];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]=maxl;
scanf("%d",&m);
for(int i=1;i<=m;i++) {
scanf("%d%d",&x,&y);
f[x][y]=f[y][x]=sqrt(pow((a[x]-a[y]),2)+pow((b[x]-b[y]),2));
}
scanf("%d%d",&s,&t);
for(int i=1;i<=n;i++)
dis[i]=f[s][i];
dis[s]=0;
for(int i=1;i<=n;i++) {
double maxn=1e9;
int k=0;
for(int j=1;j<=n;j++)
if(dis[j]<maxn&&!vis[j]){
maxn=dis[j];
k=j;
}
if(k==0)break;
else{
vis[k]=1;
for(int j=1;j<=n;j++){
if(dis[k]+f[k][j]<dis[j])
dis[j]=dis[k]+f[k][j];
}
}
}
printf("%.2lf",dis[t]);
return 0;
}
//Twenty
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int n,m,maxl=1e9,x,y,s,t,vis[110];
double a[110],b[110],f[110][110],dis[110];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
cin>>a[i]>>b[i];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]=maxl;
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
f[x][y]=f[y][x]=sqrt(pow((a[x]-a[y]),2)+pow((b[x]-b[y]),2));
}
scanf("%d%d",&s,&t);
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j&&k!=j&&k!=i&&f[i][k]+f[k][j]<f[i][j])f[i][j]=f[i][k]+f[k][j];
printf("%.2lf",f[s][t]);
return 0;
}
//Twenty
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=500000;
int n,m,s,t,first[maxn],next[maxn],wi[maxn],to[maxn],ecnt=0,dis[maxn],vis[maxn];
int add(int x,int y,int w) {
next[++ecnt]=first[x];first[x]=ecnt;to[ecnt]=y;wi[ecnt]=w;
next[++ecnt]=first[y];first[y]=ecnt;to[ecnt]=x;wi[ecnt]=w;
}
int spfa() {
queue<int>team;
dis[s]=0;
vis[s]=1;
team.push(s);
while(!team.empty()) {
int x;
x=team.front();
team.pop();
for(int i=first[x];i!=-1;i=next[i]) {
if(wi[i]+dis[x]<dis[to[i]]) {
dis[to[i]]=wi[i]+dis[x];
if(!vis[to[i]])
{vis[to[i]]=1;
team.push(to[i]);}
}
}
vis[x]=0;
}
}
int main()
{
memset(first,-1,sizeof(first));
memset(vis,0,sizeof(vis));
memset(dis,127,sizeof(dis));
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;i++) {
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
add(x,y,w);
}
spfa();
printf("%d",dis[t]);
return 0;
}
2.最小生成树
//Twenty
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iostream>
using namespace std;
int fa[10000],ans=0,k=0;
struct edge {
int u,v,w;
}e[1000];
bool cmp(const edge&a,const edge&b) {return a.w>b.w;}
int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
cin>>e[i].u>>e[i].v>>e[i].w;
sort(e+1,e+1+m,cmp);
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++) {
int u,v;
u=e[i].u;v=e[i].v;
u=find(u);v=find(v);
if(u!=v) {
ans+=e[i].w;
fa[u]=v;
k++;
if(k==n-1)break;
}
}
cout<<ans<<endl;
return 0;
}
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int ans=0,n,a[150][150],vis[150],dis[150];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>a[i][j];
memset(dis,127,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[1]=0;
for(int i=1;i<=n;i++) {
int k=0;
for(int j=1;j<=n;j++)
if(!vis[j]&&dis[j]<dis[k])
k=j;
vis[k]=1;
for(int j=1;j<=n;j++)
if(!vis[j]&&dis[j]>a[k][j])
dis[j]=a[k][j];
}
for(int i=1;i<=n;i++)
ans+=dis[i];
cout<<ans<<endl;
return 0;
}
3.dfs_spfa判负环
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=200000+29;
using namespace std;
int flag,x,y,z,T,n,m,fir[maxn],nxt[maxn<<1],to[maxn<<1],val[maxn<<1],ecnt,vis[maxn],dis[maxn];
void add(int u,int v,int w){
nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
}
void dfs_spfa(int x){
if(vis[x]) {flag=1;return;}
vis[x]=1;
for(int i=fir[x];i;i=nxt[i])
if(dis[to[i]]>val[i]+dis[x]){
dis[to[i]]=val[i]+dis[x];
dfs_spfa(to[i]);
if(flag) return;
}
vis[x]=0;
}
int main()
{
scanf("%d",&T);
while(T--){
flag=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
if(z>=0) add(y,x,z);
}
for(int i=1;i<=n;i++) dis[i]=vis[i]=0;
for(int i=1;i<=n;i++)
{dfs_spfa(i);
if(flag) break;}
if(flag) printf("YE5\n");
else printf("N0\n");
for(int i=1;i<=n;i++) fir[i]=0;
for(int j=1;j<=ecnt;j++) nxt[j]=to[j]=0;
ecnt=0;
}
return 0;
}
4.LCA
//Twenty
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2*500000;
int n,n2,n3,a,b;
int first[maxn],next[maxn],to[maxn],vis[maxn],firstarrive[maxn],R[maxn],cur[maxn];
int dp[maxn][20];
int ecnt=0;
int add(int u,int v) {
next[++ecnt]=first[u];first[u]=ecnt;to[ecnt]=v;
next[++ecnt]=first[v];first[v]=ecnt;to[ecnt]=u;
}
int cnt=0;
void dfs(int node,int dep) {
vis[node]=1;
cur[++cnt]=node;
R[cnt]=dep;
firstarrive[node]=cnt;
for(int i=first[node];i!=-1;i=next[i]) {
if(!vis[to[i]]) {
dfs(to[i],dep+1);
cur[++cnt]=node;
R[cnt]=dep;
}
}
}
void ST(int n) {
for(int i=1;i<=n;i++)
dp[i][0]=i;
for(int j=1;(1<<j)<=n;j++)
for(int i=1;(i+(1<<j)-1)<=n;i++) {
int a=dp[i][j-1],b=dp[i+(1<<(j-1))][j-1];
dp[i][j]=R[a]<R[b]?a:b;
}
}
int RMQ(int l,int r) {
int k=0;
while(l+(1<<(k+1))-1<=r) {
k++;
}
int a=dp[l][k],b=dp[r-(1<<k)+1][k];
return R[a]<R[b]?a:b;
}
int LCA(int a,int b) {
a=firstarrive[a];
b=firstarrive[b];
if(a>b)swap(a,b);
return cur[RMQ(a,b)];
}
int main()
{
memset(first,-1,sizeof(first));
scanf("%d%d%d",&n,&n2,&n3);
for(int i=1;i<n;i++) {
scanf("%d%d",&a,&b);
add(a,b);
}
dfs(n3,1);
ST(2*n);
while(n2--) {
scanf("%d%d",&a,&b);
printf("%d\n",LCA(a,b));
}
return 0;
}
//Twenty
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=5000;
int n,n2,n3,a,b;
int first[maxn],next[maxn],to[maxn],fa[maxn],vis[maxn];
int firstcheck[maxn],nextcheck[maxn],tocheck[maxn];
int ans[maxn][maxn],check[maxn][3];
int dp[maxn][20];
int ecnt=0;
int add(int u,int v) {
next[++ecnt]=first[u];first[u]=ecnt;to[ecnt]=v;
next[++ecnt]=first[v];first[v]=ecnt;to[ecnt]=u;
}
int addcheck(int u,int v) {
nextcheck[++ecnt]=firstcheck[u];firstcheck[u]=ecnt;tocheck[ecnt]=v;
nextcheck[++ecnt]=first[v];firstcheck[v]=ecnt;tocheck[ecnt]=u;
}
int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
int dfs(int node,int far) {
vis[node]=1;
for(int i=first[node];i!=0;i=next[i]) {
if(!vis[to[i]]) {
dfs(to[i],node);
}
}
fa[node]=far;
for(int i=firstcheck[node];i!=0;i=next[i]) {
if(!vis[tocheck[i]])
continue;
else ans[tocheck[i]][node]=ans[node][tocheck[i]]=find(tocheck[i]);
}
}
int main()
{
scanf("%d%d%d",&n,&n2,&n3);
for(int i=1;i<n;i++) {
scanf("%d%d",&a,&b);
add(a,b);
}
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=n2;i++) {
cin>>a>>b;
check[i][1]=a;
check[i][2]=b;
addcheck(a,b);
}
dfs(1,1);
for(int i=1;i<=n2;i++)
printf("%d\n",ans[check[i][1]][check[i][2]]);
return 0;
}
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=500005;
using namespace std;
int n,q,s,x,y,fir[maxn],next[maxn*2],to[maxn*2],fa[maxn][20],vis[maxn],R[maxn];
int ecnt;
inline int add(int u,int v){
next[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;
next[++ecnt]=fir[v];fir[v]=ecnt;to[ecnt]=u;
}
int dfs(int x,int f) {
vis[x]=1;
R[x]=R[f]+1;
fa[x][0]=f;
for(int i=fir[x];i!=0;i=next[i]) {
if(!vis[to[i]]) {
dfs(to[i],x);
}
}
}
void init() {
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i<=n;i++)
{
if(fa[i][j-1]!=-1)
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
int LCA(int a,int b){
if(R[a]<R[b]) swap(a,b);
int i;
for(i=0;(1<<i)<=R[a];i++);
i--;
for(int j=i;j>=0;j--) {
if(R[a]-(1<<j)>=R[b])
a=fa[a][j];
}
if(a==b) return a;
for(int j=i;j>=0;j--) {
if(fa[a][j]!=-1&&fa[a][j]!=fa[b][j]) {
a=fa[a][j];
b=fa[b][j];
}
}
return fa[a][0];
}
int main()
{
memset(fa,-1,sizeof(fa));
scanf("%d%d%d",&n,&q,&s);
for(int i=1;i<n;i++) {
scanf("%d%d",&x,&y);
add(x,y);
}
dfs(s,s);
init();
while(q--) {
scanf("%d%d",&x,&y);
printf("%d\n",LCA(x,y));
}
return 0;
}
5.tarjan
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
const int maxn=(1e5+299)*2;
using namespace std;
int ecnt,v[maxn],fir[maxn],nxt[maxn],to[maxn],dp[maxn],dfn[maxn],low[maxn];
int clock,nn,xn,m,sccno[maxn],ans;
void add(int x,int y){
nxt[++ecnt]=fir[x]; fir[x]=ecnt; to[ecnt]=y;
}
stack<int>sta;
void tarjan(int x){
dfn[x]=low[x]=++clock;
sta.push(x);
for(int i=fir[x];i;i=nxt[i]){
if(!dfn[to[i]]){
tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}
else if(!sccno[to[i]])
low[x]=min(low[x],dfn[to[i]]);
}
if(dfn[x]==low[x])
{
xn++;
for(;;){
int u=sta.top();
sta.pop();
sccno[u]=xn;
v[xn]+=v[u];
if(u==x) break;
}
}
}
void Dp(int x){
if(dp[x]) return;
int now=0;
for(int i=fir[x];i;i=nxt[i]){
Dp(to[i]);
now=max(now,dp[to[i]]);
}
dp[x]=v[x]+now;
}
int main()
{
scanf("%d%d",&nn,&m);
xn=nn;
for(int i=1;i<=nn;i++) scanf("%d",&v[i]);
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=1;i<=nn;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=nn;i++)
for(int j=fir[i];j;j=nxt[j]){
int u=i,v=to[j];
if(sccno[u]!=sccno[v])
add(sccno[u],sccno[v]);
}
for(int i=nn+1;i<=xn;i++){
Dp(i);
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
return 0;
}
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=(100000+299)*2;
using namespace std;
int clock,ecnt,n,m,fir[maxn],nxt[maxn],to[maxn],dfn[maxn],low[maxn];
int cut[maxn],ans;
void add(int x,int y){
nxt[++ecnt]=fir[x]; fir[x]=ecnt; to[ecnt]=y;
nxt[++ecnt]=fir[y]; fir[y]=ecnt; to[ecnt]=x;
}
void tarjan(int x,int rt){
int rc=0;
dfn[x]=low[x]=++clock;
for(int i=fir[x];i;i=nxt[i]){
if(!dfn[to[i]]){
tarjan(to[i],rt);
low[x]=min(low[x],low[to[i]]);
if(low[to[i]]>=dfn[x]&&x!=rt) cut[x]=1;
if(x==rt) rc++;
}
else low[x]=min(low[x],dfn[to[i]]);
}
if(x==rt&&rc>=2) cut[x]=1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i,i);
for(int i=1;i<=n;i++)
if(cut[i]) ans++;
printf("%d\n",ans);
for(int i=1;i<=n;i++)
if(cut[i]) printf("%d ",i);
return 0;
}
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
typedef long long LL;
using namespace std;
const int maxn=10000+299;
const int maxm=100000*2+299;
int T,n,m,x,y,fir[maxn],nxt[maxm],to[maxm],fa[maxn],cc,cut[maxm],dfn[maxn],id[maxm],low[maxn],dfs_clock,ecnt;
void add(int x,int y,int tot) {
nxt[++ecnt]=fir[x]; fir[x]=ecnt; to[ecnt]=y; id[ecnt]=tot;
nxt[++ecnt]=fir[y]; fir[y]=ecnt; to[ecnt]=x; id[ecnt]=tot;
}
void clear() {
memset(fir,0,sizeof(fir));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(cut,0,sizeof(cut));
memset(fa,0,sizeof(fa)); ecnt=0;
dfs_clock=0;
}
void tarjan(int x) {
dfn[x]=low[x]=++dfs_clock;
for(int i=fir[x];i;i=nxt[i]) {
if(!dfn[to[i]]) {
fa[to[i]]=i;
tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}
else if(id[fa[x]]!=id[i]) low[x]=min(low[x],dfn[to[i]]);
}
if(fa[x]&&dfn[x]==low[x]) {
cc++;
cut[id[fa[x]]]=1;
}
}
int main()
{
scanf("%d",&T);
while(T) {
clear();
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) {
scanf("%d%d",&x,&y);
add(x,y,i);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
printf("%d\n",cc);
for(int i=1;i<=m;i++)
if(cut[i]) { cc--; if(cc) printf("%d ",i); else printf("%d\n",i);}
--T;
if(T) printf("\n");
}
return 0;
}
6.拓扑排序
//Twenty
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=50000;
const int maxm=2.5*maxn;
int n,m,a,b,ans;
int first[maxn],next[maxm],to[maxm],integ[maxn];
int ecnt=0;
int add(int u,int v){
next[++ecnt]=first[u];first[u]=ecnt;to[ecnt]=v;}
int toposort(){
queue<int>team;
for(int i=1;i<=n;i++){if(integ[i]==0) team.push(i);}
while(!team.empty() ) {
int x=team.front(); team.pop();
for(int i=first[x];i!=0;i=next[i]){
integ[to[i]]--;
if(integ[to[i]]==0)team.push(to[i]);
}
}
for(int i=1;i<=n;i++)
if(integ[i])ans++;
}
int main()
{
scanf("%d",&n);
scanf("%d",&m);
for(int i=1;i<=m;i++) {
scanf("%d%d",&a,&b);
integ[b]++;
add(a,b);
}
toposort();
if(ans==0)printf("o(∩_∩)o");
else printf("T_T\n%d",ans);
return 0;
}
7.匈牙利算法
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=2005;
int n,m,u,v,e,ecnt,ans,fir[maxn],next[maxn*maxn],to[maxn*maxn],f[maxn],pre[maxn];
using namespace std;
void add(int u,int v){
next[++ecnt]=fir[u];to[ecnt]=v;fir[u]=ecnt;
}
int find(int x){
for(int i=fir[x];i;i=next[i])
if(!f[to[i]]){
f[to[i]]=1;
if(!pre[to[i]]||find(pre[to[i]])){
pre[to[i]]=x;
return 1;
}
}
return 0;
}
int main()
{
scanf("%d%d%d",&n,&m,&e);
for(int i=1;i<=e;i++){
scanf("%d%d",&u,&v);
if(u<=m&&v<=m) add(u,v+1000);
}
for(int i=1;i<=n;i++){
memset(f,0,sizeof(f));
ans+=find(i);
}
printf("%d\n",ans);
return 0;
}