ACM模版——图论
//===========================================\\
| 邻接表 |
\\===========================================//
struct node { int num,d; node *next; }*head[1010],*v;
void input(int a,int b,int c)
{
v=new node;
v->num=b;
v->d=c;
v->next=head[a];
head[a]=v;
} //不同组数据,记得要初始化head[i]=NULL
//===========================================\\
| Dijkstra 算法 |
\\===========================================//
int cov[1010],dis[1010],path[1010],n;
const int INF=10000;
void dj(int s,int t) // 源s,目标t
{
int i,min,k=s;
memset(cov,0,sizeof(cov));
cov[k]=1;
for (int i=1; i<=n; i++) dis[i]=INF;
path[k]=-1;
dis[k]=0;
while ( !cov[t] ) // 或for(i=1; i<n; i++)
{
for ( v=head[k]; v!=NULL; v=v->next)
if ( !cov[v->num] && dis[v->num]>dis[k]+v->d )
{
dis[v->num]=dis[k]+v->d;
path[v->num]=k;
}
for (i=1,min=INF; i<=n; i++ )
if ( !cov[i] && dis[i]<min )
{
min=dis[i];
k=i;
}
cov[k]=1;
}
}
//===========================================\\
| SPFA算法 |
\\===========================================//
int dis[1010],path[1010],clu[1010],n;
bool cov[1010]; //判断是否入队
bool spfa(int s)
{
int i;
queue<int> q;
q.push(s);
memset(clu,0,sizeof(clu));
clu[s]++;
memset(cov,0,sizeof(cov));
path[s]=-1;
for (i=1; i<=n; i++) dis[i]=INF;
dis[s]=0;
while ( !q.empty() )
{
i=q.front();
q.pop();
for ( v=head[i]; v!=NULL; v=v->next )
if ( dis[v->num]>dis[i]+v->d )
{
dis[v->num]=dis[i]+v->d;
path[v->num]=i;
if ( !cov[v->num])
{
clu[v->num]++;
if ( clu[v->num]>n ) return 0;
cov[v->num]=1;
q.push(v->num);
}
}
}
return true;
}
//===========================================\\
| Floyd算法 |
\\===========================================//
int dis[1010][1010],n,path[1010];
void Floyd()
{
int i,j,k;
for (i=1; i<=n; i++) dis[i][i]=0;
for (k=1; k<=n; k++)
for (i=1; i<=n; i++)
for (j=1; j<=n; j++)
if ( dis[i][k]<INF && dis[k][j]<INF && dis[i][j]<dis[i][k]+dis[k][j] )
{
path[i][j]=k;
dis[i][j]=dis[i][k]+dis[k][j];
}
}
//===========================================\\
| 二分图 |
\\===========================================//
//最小覆盖点数(所有边与这些点关联)=最大匹配数
//最大独立集点数(任意两点不相连)=节点数-最大匹配数
//最小路径覆盖数=原图节点数-最大匹配数(有向无环图)
Ps:最小覆盖点数,最大独立点数是针对二分图说的
常见建图模型:
1、 行列匹配法(1):“行”为x集,“列”为y集
2、 方阵染色法(1)
3、 反建法(2)
4、 拆点法(3):若i->j存在,建边i->j’
//===========================================\\
| Hungary 算法 |
\\===========================================//
bool cov[510]; //在每次找增广路时,判断点是否到达过
int x[510],y[510]; //记录与哪点相匹配,若未匹配为-1
int k,m,n;
bool sb(int a) //找增广路
{
node *p;
for ( p=head[a]; p!=NULL; p=p->next)
{
if ( !cov[p->num] )
{
cov[p->num]=true;
if ( y[p->num]==-1 || sb(y[p->num]) )
{
x[a]=p->num;
y[p->num]=a;
return true;
}
}
}
return false;
}
int hungary()
{
int i,ans=0;
memset(x,0xff,sizeof(x));
memset(y,0xff,sizeof(y));
for ( i=1; i<=m; i++ ) if ( x[i]==-1 )
{
memset(cov,false,sizeof(cov));
if ( sb(i) ) ans++;
}
return ans;
}
//===========================================\\
| Hopcroft Karp算法 |
\\===========================================//
//===========================================\\
| Kruskal 算法 |
\\===========================================//
struct tmp { int x,y,cost; }road[5000];
bool cmp(tmp a,tmp b) { return a.cost<b.cost; }
int kru()
{
int i=0,j=n-1,ans=0;
for (int k=1; k<=n; k++) g[k]=r[k]=k; //并查集
sort(road+1,road+n*(n-1)/2+1,cmp); //边升序排序
while ( j )
{
i++;
if ( g[road[i].x]!=g[road[i].y] )
{
ans+=road[i].cost;
update(road[i].x,road[i].y); //并查集
j--;
}
}
return ans; //返回最小总权值
}
//===========================================\\
| Prim 算法 |
\\===========================================//
int dis[1010],path[1010],n;
bool cov[1010];
int prim()
{
int i,j,min,s=1,k,ans=0;
memset(cov,0,sizeof(cov));
cov[s]=1;
for (i=1; i<=n; i++) dis[i]=INF;
path[s]=-1;
for (j=1; j<n; j++)
{
cov[s]=1;
for (p=head[s]; p!=NULL; p=p->next)
if ( !cov[p->num] && dis[p->num]>p->d )
{
dis[p->num]=p->d;
path[p->num]=s;
}
for (i=1,min=INF; i<=n; i++)
if ( !cov[i] && dis[i]<min )
{
min=dis[i];
s=i;
}
ans+=min;
}
return ans;
}
//===========================================\\
| 拓扑排序 |
\\===========================================//
int in[100010],s[100010],path[100010],n;
bool Toposort() //path[i]记录i前一个点
{
int i,j=0;
queue<int> q;
for ( i=1; i<=n; i++) if ( !in[i] )
{
q.push(i);
path[i]=-1;
}
while ( !q.empty() )
{
s[++j]=q.front();
q.pop();
for (node *p=head[s[j]]; p!=NULL; p=p->next)
if ( !--in[p->num] )
{
q.push(p->num);
path[p->num]=s[j];
}
}
if ( j<n ) return false;
else return true;
}
浙公网安备 33010602011771号