板子们 (未完待续)

时间:2022-07-05 00:25:59

1.数学

1.1、(扩展)欧几里得

板子们 (未完待续)板子们 (未完待续)
void gcd(int a,int b,int &d,int &x,int &y)
{
if(!b) { d=a; x=1; y=0; }
else { gcd(b,a%b,d,y,x); y-=x*(a/b); }
}
View Code

 

1.2、同余方程

板子们 (未完待续)板子们 (未完待续)
//解同余方程 ax≡c(mod b)
//转化为ax-by=c
void solve()
{
gcd(a,b,g,x0,y0);
if(c%g) printf("no solution");
x
=c/g*x0; y=c/g*y0;
printf(
"任意一组解:%d",x);
a
/=g; b/=g;
x
=(x%b+b)%b
printf(
"最小x正整数解:%d",x);
}
View Code

 

扩展欧几里得、同余方程 解析:http://www.cnblogs.com/TheRoadToTheGold/p/6645383.html

 

1.3、快速幂

板子们 (未完待续)板子们 (未完待续)
int quickmul(int a,int b,int p)
{
int ans=1;
for(;b;b>>=1,a=a*a%p)
if(b&1) ans=ans*a%p;
return ans;
}
View Code

 

1.4、素数判定

 

1.4.1. 费马小定理  若 a、p互质 ,则 a^(p-1) %p=1

缺陷:Carmichael数可以通过素数判定

O(次数*log)

板子们 (未完待续)板子们 (未完待续)
#include<ctime>
#include
<cstdio>
#include
<cstdlib>
using namespace std;
typedef
long long LL;
LL p;
bool flag;
LL mul(LL a,LL b)
{
a
%=p; b%=p;
LL r
=0;
while(b)
{
if(b&1) { b--; r=(r+a)%p; }
a
<<=1; a%=p; b>>=1;
}
return r;
}
LL qm(LL a,LL b)
{
LL r
=1;
while(b)
{
if(b&1) r=mul(r,a);
b
>>=1; a=mul(a,a);
}
return r;
}
int main()
{
scanf(
"%lld",&p);
srand(time(
0));
for(int i=1;i<=15;i++)
{
LL a
=rand()%(p-1)+1;
LL x
=qm(a,p-1);
if(x!=1) { flag=1; break; }
}
if(flag) printf("No");
else printf("Yes");
}
View Code

 

1.4.2 Miller_Rabin

不会误判Carmichael数,误判概率为1/4^T

判断四五次大概够了

板子们 (未完待续)板子们 (未完待续)
#include<ctime>
#include
<cstdio>
#include
<cstdlib>
using namespace std;
typedef
long long LL;
LL p;
LL mul(LL a,LL b)
{
LL r
=0;
while(b)
{
if(b&1) r+=a,r%=p;
a
<<=1; a%=p; b>>=1;
}
return r;
}
LL qm(LL a,LL b)
{
LL r
=1;
while(b)
{
if(b&1) r=mul(r,a);
a
=mul(a,a); b>>=1;
}
return r;
}
bool Miller_Rabin()
{
if(p==2) return true;
if(p==1 || p%2==0) return false;
LL x,y,m,k
=0,a;
m
=p-1;
while(m%2==0) k++,m>>=1;
int T=4;
while(T--)
{
a
=rand()%(p-1)+1;
x
=qm(a,m);
for(int i=1;i<=k;i++)
{
y
=mul(x,x);
if(x&1 && y==1 && x!=1 && x!=p-1) return false;
x
=y;
}
if(x!=1) return false;
}
return true;
}
int main()
{
srand(time(
0));
scanf(
"%lld",&p);
if(Miller_Rabin()) printf("Yes");
else printf("No");
}
View Code

 

1.5  素数相关

 

1.5.1 素数线性筛

板子们 (未完待续)板子们 (未完待续)
void solve()
{
for(int i=2;i<=N;i++)
{
if(!v[i]) prime[++cnt]=i;
for(int j=1;j<=cnt;j++)
{
if(prime[j]*i>=N) break;
v[prime[j]
*i]=true;
if(i%prime[j]==0) break;
}
}
}
View Code

 

1.5.2 唯一分解定理

板子们 (未完待续)板子们 (未完待续)
#include<cmath>
#include
<cstdio>
#include
<cstring>
using namespace std;
int p[100001],c[100001];
int main()
{
int n,sum;
while(scanf("%d",&n)!=EOF)
{
memset(c,
0,sizeof(c));
sum
=0;
int m=sqrt(n);
for(int i=2;i<=m;i++)
if(n%i==0)
{
p[
++sum]=i;
while(n%i==0) n/=i,c[sum]++;
}
if(n>1) p[++sum]=n,c[sum]++;
for(int i=1;i<=sum;i++) printf("%d %d\n",p[i],c[i]);
}
}
View Code

 

1.5.3 阶乘的质因数分解

板子们 (未完待续)板子们 (未完待续)
for(int i=1;prime[i]<=n;i++)
{
int t=n;
while(t)
{
cnt[i]
+=t/prime[i];
t
/=prime[i];
}
}
View Code

 

1.6 欧拉函数

原理 请转至http://www.cnblogs.com/TheRoadToTheGold/p/6598367.html

 

1.6.1  欧拉函数计算

板子们 (未完待续)板子们 (未完待续)
void euler(int n)
{
int ans=n;
for(int i=2;i*i<=n;i++)
if(n%i==0)
{
ans
=ans/i*(i-1);
while(n%i==0) n/=i;
}
if(n>1) ans=ans/n*(n-1);
}
View Code

 

 

1.6.2 欧拉筛

O(n)

板子们 (未完待续)板子们 (未完待续)
void euler_table()
{
phi[
1]=1;
for(int i=2;i<=n;i++)
{
if(!v[i])
{
prime[
++cnt]=i;
phi[i]
=i-1;
}
for(int j=1;j<=cnt;j++)
{
if(prime[j]*i>=N) break;
v[prime[j]
*i]=true;
if(i%prime[j]) phi[prime[j]*i]=phi[i]*(prime[j]-1);
else
{
phi[prime[j]
*i]=prime[j]*phi[i];
break;
}
}
}
}
View Code

 

1.6.3 埃拉托斯特尼筛

O(nlog²n)

板子们 (未完待续)板子们 (未完待续)
int eratosthenes(int n)
{
int ans=n,k=n;
int m=sqrt(n);
for(int i=2;i<=m;i++)
if(n%i==0)
{
ans
=ans/i*(i-1);
for(int j=1;j*i<=k;j++) v[i*j]=false;
while(n%i==0) n/=i;
}
if(n>1)
{
ans
=ans/n*i;
for(int j=1;j*i<=k;j++) v[i*j]=false;
}
return ans;
}
View Code

 

1.6.4 杜教筛

待填坑

 

1.7 莫比乌斯函数

原理转至 http://www.cnblogs.com/TheRoadToTheGold/p/6598088.html

 

1.7.1 线性筛 

板子们 (未完待续)板子们 (未完待续)
void mobius()
{
mul[
1]=1;
for(int i=2;i<=n;i++)
{
if(v[i])
{
prime[
++cnt]=i;
mul[i]
=-1;
}

for(int j=1;j<=cnt;j++)
{
if(i*prime[j]>=N) break;
v[i
*prime[j]]=true;
if(i%prime[j]==0) { mul[i*prime[j]]=0; break; }
mul[i
*prime[j]]=-mul[i];
}
}
}
View Code

 

1.7.2 杜教筛

待填坑

 

1.8 逆元

只有 a p 互质,a才有关于p的逆元

原理请见:http://www.cnblogs.com/linyujun/p/5194184.html

 

1.8.1   费马小定理  限制条件:p是质数

板子们 (未完待续)板子们 (未完待续)
int quickpow(int a,int b,int p)
{
int r=1;
while(b)
{
if(b&1) r8=a,r%=p;
b
>>=1; a*=a; a%=p;
}
return r;
}
void solve(int a,int p)
{
if(prime(p)) printf("%d",quickpow(a,p-2,p));
}
View Code

 

1.8.2    扩展欧几里得

板子们 (未完待续)板子们 (未完待续)
void exgcd(int a,int b,int& g,int& x,int& y)
{
if(!b) { g=a; x=1; y=0; }
else { exgcd(b,a%b,g,y,x); y-=x*(a/b); }
}
void solve()
{
exgcd(a,b,g,x,y);
if(g!=1) return;
printf(
"%d",(x%p+p)%p);
}
View Code

 

1.8.3 递推 限制条件:p是质数

板子们 (未完待续)板子们 (未完待续)
void solve(int p)
{
inv[
1]=1;
for(int i=2;i<N;i++) inv[i]=(p-p/i)*inv[p%i]%p;
}
View Code

 

 

1.9 中国剩余定理

 

1.9.1 大数翻倍法

板子们 (未完待续)板子们 (未完待续)
#include<cstdio>
using namespace std;
int n,a[11],b[11];
long long get_gcd(long long a,long long b)
{
return !b ? a:get_gcd(b,a%b);
}
int main()
{
scanf(
"%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
long long ans=b[1];
long long lcm=a[1];
for(int i=2;i<=n;i++)
{
while(ans%a[i]!=b[i]) ans+=lcm;
long long gcd=get_gcd(lcm,(long long)a[i]);
lcm
=lcm/gcd*(long long)a[i];
}
printf(
"%lld",ans);
}
View Code

 

1.9.2 中国剩余定理 互质版

板子们 (未完待续)板子们 (未完待续)
#include<cstdio>
using namespace std;
int n;
int m[11],a[11];
long long M=1,ans,Mi[11],e[11];
void exgcd(long long a,long long b,long long &x,long long &y)
{
if(!b) x=1,y=0;
else { exgcd(b,a%b,y,x); y-=x*(a/b); }
}
int main()
{
scanf(
"%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&m[i],&a[i]),M*=m[i];
for(int i=1;i<=n;i++) Mi[i]=M/m[i];
long long x,y;
for(int i=1;i<=n;i++)
{
exgcd(Mi[i],m[i],x,y);
x
=(x%m[i]+m[i])%m[i];
e[i]
=Mi[i]*x%M;
}
for(int i=1;i<=n;i++) ans=(ans+e[i]*a[i])%M;
printf(
"%lld",ans);
}
View Code

 

这两个原理见:http://www.cnblogs.com/TheRoadToTheGold/p/6638430.html

  

1.9.3 中国剩余定理 非互质版

待填坑

 

1.10 卢卡斯定理

 

1.10.1 互质版

 

1.10.1.1  预处理阶乘

板子们 (未完待续)板子们 (未完待续)
#include<cstdio>
using namespace std;
typedef
long long LL;
LL f[
100001];
void pre(int p)
{
f[
0]=1;
for(int i=1;i<=p;i++) f[i]=f[i-1]*i%p;
}
int pow(LL a,int b,int p)
{
LL r
=1;
while(b)
{
if(b&1) r*=a,r%=p;
b
>>=1; a*=a; a%=p;
}
return r;
}
int C(int n,int m,int p)
{
if(m>n) return 0; //如果m>n,那么原来的m<n-p,即m与n之间至少有一个p的倍数,那么结果为0
return f[n]*pow(f[m]*f[n-m],p-2,p)%p;
}
/*int Lucas(int n,int m,int p)
{
if(!m) return 1;
return (C(n%p,m%p,p)*Lucas(n/p,m/p,p))%p;
}
*/
int Lucas(int n,int m,int p) //非递归版,上面是递归版
{
LL ans
=1;
for(;m;n/=p,m/=p) ans=ans*C(n%p,m%p,p)%p;
return ans;
}
int main()
{
int T,n,m,p;
scanf(
"%d",&T);
while(T--)
{
scanf(
"%d%d%d",&n,&m,&p);
pre(p);
printf(
"%d\n",Lucas(n,m,p));
}
}
View Code

 

1.10.1.2  阶乘不能预处理

板子们 (未完待续)板子们 (未完待续)
#include<cstdio>
using namespace std;
typedef
long long LL;
/*int pow(LL a,int b,int p)
{
LL r=1;
while(b)
{
if(b&1) r*=a,r%=p;
b>>=1; a*=a; a%=p;
}
return r;
}
*/
void exgcd(int a,int b,LL &x,LL &y)
{
if(!b) { x=1; y=0; }
else { exgcd(b,a%b,y,x); y-=x*(a/b); }
}
int inv(int x,int p)
{
//return pow(x,p-2,p);
LL x0,y0;
exgcd(x,p,x0,y0);
return (x0%p+p)%p;
}
int C(int n,int m,int p)
{
if(n<m) return 0;
LL r
=1;
//for(int i=m+1;i<=n;i++) r=r*i%p*inv(i-m,p)%p; TLE
for(int i=1;i<=m;i++) r=r*(n-i+1)%p*inv(i,p)%p;
return r;
}
int Lucas(int n,int m,int p)
{
LL ans
=1;
for(;m;n/=p,m/=p)
ans
=ans*C(n%p,m%p,p)%p;
return ans;
}
int main()
{
int n,m,p;
while(scanf("%d%d%d",&n,&m,&p)!=EOF)
printf(
"%d\n",Lucas(n,m,p));
}
View Code

 

 1.10.2  扩展卢卡斯

 待填坑

 

1.11 Catalan数

板子们 (未完待续)板子们 (未完待续)
#include<cstdio>
#define mod 100000007
using namespace std;
long long f[20000];
int main()
{
int n;
scanf(
"%d",&n);
f[
0]=f[1]=1;
for(int i=2;i<=n;i++)
for(int j=1;j<=i;j++)
f[i]
=(f[i]+f[j-1]*f[i-j]%mod)%mod;
//for(int i=2;i<=n;i++) f[i]=f[i-1]*(4*i-2)/(i+1);
printf("%lld",f[n]);
}
View Code

 

1.12 矩阵树定理

板子们 (未完待续)板子们 (未完待续)
#include<cstdio>
#include
<algorithm>
using namespace std;
int n,m;
long long t,C[101][101],ans;
long long Matrix_tree()
{
ans
=1;
for(int i=1;i<n;i++)
{
for(int j=i+1;j<n;j++)
while(C[j][i])
{
t
=C[i][i]/C[j][i];
for(int k=i;k<n;k++) C[i][k]-=C[j][k]*t;
for(int k=i;k<n;k++) swap(C[i][k],C[j][k]);
ans
=-ans;
}
if(!C[i][i]) return 0;
ans
*=C[i][i];
}
return ans;
}
int main()
{
scanf(
"%d%d",&n,&m);
int u,v;
while(m--)
{
scanf(
"%d%d",&u,&v);
u
--; v--;
C[u][v]
--; C[v][u]--;
C[u][u]
++; C[v][v]++;
}
printf(
"%lld",Matrix_tree());
}
View Code

 

2.图论

2.1 最短路

 

2.1.1 Floyd 

板子们 (未完待续)板子们 (未完待续)
  scanf("%d%d",&n,&m);
memset(f,
63,sizeof(f));
while(m--)
{
scanf(
"%d%d%d",&a,&b,&c);
f[a][b]
=f[b][a]=min(f[a][b],c);
}
for(int i=1;i<=n;i++) f[i][i]=0;
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]
=min(f[i][j],f[i][k]+f[k][j]);
View Code

 

2.1.2 Dijkstra

 

2.1.2.1 普通Dijkstra

板子们 (未完待续)板子们 (未完待续)
void dijkstra()
{
memset(v,
false,sizeof(v));
memset(dis,
63,sizeof(dis));
v[
1]=true;
dis[
1]=0;
int minn,k;
for(int i=1;i<n;i++)
{
k
=0;
minn
=0x7fffffff;
for(int j=1;j<=n;j++)
if(!v[j] && dis[j]<minn ) minn=dis[j],k=j;
if(!k) break;
v[k]
=true;
for(int j=1;j<=n;j++)
if(dis[j]>dis[k]+e[k][j] ) dis[j]=dis[k]+e[k][j];
}
}
View Code

 

2.1.2.2 堆优化

板子们 (未完待续)板子们 (未完待续)
#include<cstdio>
#include
<queue>
#include
<cstring>
#define N 55000
#define M 1000000
using namespace std;
int n,m,s,t,tot;
int nxt[M],to[M],front[N],cap[M];
int DIS[N];
bool vis[N];
struct edge
{
int number,dis;
bool operator <(edge b) const
{
return dis>b.dis;
}
}now,nt;
priority_queue
<edge>q;
void add(int u,int v,int w)
{
to[
++tot]=v; nxt[tot]=front[u]; front[u]=tot; cap[tot]=w;
to[
++tot]=u; nxt[tot]=front[v]; front[v]=tot; cap[tot]=w;
}
bool dijkstra()
{
for(int i=1;i<=n;i++) DIS[i]=2e9;
q.push((edge){s,
0});
DIS[s]
=0;
while(!q.empty())
{
now
=q.top();q.pop();
if(vis[now.number]) continue;
vis[now.number]
=true;
for(int i=front[now.number];i;i=nxt[i])
{
if(DIS[to[i]]>DIS[now.number]+cap[i])
{
DIS[to[i]]
=DIS[now.number]+cap[i];
q.push((edge){to[i],DIS[to[i]]});
}
}
}
printf(
"%d",DIS[t]);
}

int main()
{
int u,v,w;
scanf(
"%d%d%d%d",&n,&m,&s,&t);
while(m--)
{
scanf(
"%d%d%d",&u,&v,&w);
add(u,v,w);
}
dijkstra();
}
View Code

 

 

2.1.3 spfa

板子们 (未完待续)板子们 (未完待续)
void spfa()
{
memset(dis,
63,sizeof(dis));
dis[
1]=0; q.push(1); vis[1]=true;
int now;
while(!q.empty())
{
now
=q.front(); q.pop(); vis[now]=false;
for(int i=front[now];i;i=nxt[i])
if(dis[to[i]]>dis[now]+val[i])
{
dis[to[i]]
=dis[now]+val[i];
if(!vis[to[i]]) vis[to[i]]=true,q.push(to[i]);
}
}
}
View Code

 

2.2 次短路

注:代码是严格的次短路

板子们 (未完待续)板子们 (未完待续)
#include<queue>
#include
<cstdio>
#include
<cstring>
#define N 5001
#define M 100001
using namespace std;
int front[N],to[M<<1],nxt[M<<1],val[M<<1],from[M<<1],tot;
int dis1[N],dis2[N];
bool vis[N];
queue
<int>q;
void add(int u,int v,int w)
{
to[
++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w; from[tot]=u;
to[
++tot]=u; nxt[tot]=front[v]; front[v]=tot; val[tot]=w; from[tot]=v;
}
void spfa(int s,int *dis)
{
//memset(dis,63,sizeof(dis));
memset(vis,false,sizeof(vis));
q.push(s);
vis[s]
=true;
dis[s]
=0;
int now;
while(!q.empty())
{
now
=q.front();
q.pop();
vis[now]
=false;
for(int i=front[now];i;i=nxt[i])
if(dis[to[i]]>dis[now]+val[i])
{
dis[to[i]]
=dis[now]+val[i];
if(!vis[to[i]])
{
vis[to[i]]
=true;
q.push(to[i]);
}
}
}
}
int main()
{
int n,m;
scanf(
"%d%d",&n,&m);
int u,v,w;
for(int i=1;i<=m;i++)
{
scanf(
"%d%d%d",&u,&v,&w);
add(u,v,w);
}
memset(dis1,
63,sizeof(dis1));
memset(dis2,
63,sizeof(dis2));
spfa(
1,dis1);
spfa(n,dis2);
int minn=dis1[n],tmp,ans=0x7fffffff;
for(int i=1;i<=tot;i++)
{
u
=from[i]; v=to[i];
tmp
=dis1[u]+val[i]+dis2[v];
if(tmp>minn && tmp<ans) ans=tmp;
}
printf(
"%d",ans);
}
View Code

 

2.3 k短路

注:代码是不严格的k短路

http://www.cnblogs.com/TheRoadToTheGold/p/7416264.html

板子们 (未完待续)板子们 (未完待续)
#include<queue>
#include
<cstdio>
#include
<cstring>
#define N 1001
#define M 100001
using namespace std;
int n,s,t,k;
int dis1[N];
bool vis[N];
int front[N],to[M],nxt[M],val[M],tot;
int front2[N],to2[M],nxt2[M],val2[M],tot2;
struct node
{
int num,dis;
bool operator < (node p) const
{
return dis+dis1[num]>p.dis+dis1[p.num];
}
}now,nt;
void add(int u,int v,int w)
{
to[
++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w;
to2[
++tot2]=u; nxt2[tot2]=front2[v]; front2[v]=tot2; val2[tot2]=w;
}
void init()
{
int m,u,v,w;
scanf(
"%d%d",&n,&m);
while(m--)
{
scanf(
"%d%d%d",&u,&v,&w);
add(u,v,w);
}
scanf(
"%d%d%d",&s,&t,&k);
}
void spfa()
{
memset(dis1,
63,sizeof(dis1));
queue
<int>q;
dis1[t]
=0;
vis[t]
=true;
q.push(t);
int now;
while(!q.empty())
{
now
=q.front();
q.pop();
vis[now]
=false;
for(int i=front2[now];i;i=nxt2[i])
if(dis1[to2[i]]>dis1[now]+val2[i])
{
dis1[to2[i]]
=dis1[now]+val2[i];
if(!vis[to2[i]])
{
q.push(to2[i]);
vis[to2[i]]
=true;
}
}
}
}
void Astar()
{
if(dis1[s]>1e9)
{
printf(
"-1");
return;
}
if(s==t) k++;
int cnt=0,last=-1;
priority_queue
<node>q;
now.num
=s;
now.dis
=0;
q.push(now);
while(!q.empty())
{
now
=q.top();
q.pop();
if(now.num==t)
{
cnt
++;
if(cnt==k)
{
printf(
"%d",now.dis);
return;
}
}
for(int i=front[now.num];i;i=nxt[i])
{
nt.num
=to[i];
nt.dis
=now.dis+val[i];
q.push(nt);
}
}
printf(
"-1");
}
int main()
{
init();
spfa();
Astar();
}
View Code

 

2.4 最小生成树

 

2.4.1 prim

板子们 (未完待续)板子们 (未完待续)
#include<cstdio>
#include
<cstring>
using namespace std;
int a[501][501],minn[501];
bool vis[501];
int main()
{
int n,m;
scanf(
"%d%d",&n,&m);
int u,v,w;
memset(a,
63,sizeof(a));
while(m--)
{
scanf(
"%d%d%d",&u,&v,&w);
if(w<a[u][v]) a[u][v]=a[v][u]=w;
}
memset(minn,
63,sizeof(minn));
minn[
1]=0;
int tmp,k,ans=0;
for(int i=1;i<=n;i++)
{
tmp
=2e9;
for(int j=1;j<=n;j++)
if(!vis[j] && minn[j]<tmp)
{
tmp
=minn[j];
k
=j;
}
ans
+=minn[k];
vis[k]
=true;
for(int j=1;j<=n;j++)
if(!vis[j] && a[k][j]<minn[j]) minn[j]=a[k][j];
}
printf(
"%d",ans);
}
View Code

 

2.4.2 Kruskal

板子们 (未完待续)板子们 (未完待续)
#include<cstdio>
#include
<algorithm>
using namespace std;
int fa[5001];
struct node
{
int u,v,w;
}e[
200001];
bool cmp(node p,node q)
{
return p.w<q.w;
}
int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); }
int main()
{
int n,m;
scanf(
"%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
sort(e
+1,e+m+1,cmp);
for(int i=1;i<=n;i++) fa[i]=i;
int tot=0;
int r1,r2,i=1,ans=0;
while(tot<n-1)
{
r1
=find(e[i].u);
r2
=find(e[i].v);
if(r1!=r2)
{
fa[r1]
=r2;
ans
+=e[i].w;
tot
++;
}
i
++;
}
printf(
"%d",ans);
}
View Code

 

2.5 最小树形图

板子们 (未完待续)板子们 (未完待续)
#include<cstdio>
#include
<cstring>
#define N 1005
#define M 10005
#define inf 2e9
using namespace std;
struct node
{
int u,v,w;
}e[M];
int in[N],pre[N],vis[N],col[N],id[N];
int n,m;
int directed_MST()
{
int tot=n+1,root=0,ans=0,cirnum=0,to;
while(1)
{
for(int i=0;i<tot;i++) in[i]=inf;
for(int i=1;i<=m;i++)
if(e[i].u!=e[i].v && in[e[i].v]>e[i].w)
{
in[e[i].v]=e[i].w;
pre[e[i].v]
=e[i].u;
}
cirnum
=0;
memset(vis,
-1,sizeof(vis));
memset(col,
-1,sizeof(col));
in[root]=0;
for(int i=0;i<tot;i++)
{
ans
+=in[i];
to
=i;
while(vis[to]!=i && col[to]==-1 && to!=root)
{
vis[to]
=i;
to
=pre[to];
}
if(to!=root && col[to]==-1)
{
for(int nt=pre[to];nt!=to;nt=pre[nt])
col[nt]
=cirnum;
col[to]
=cirnum++;
}
}
if(!cirnum) return ans;
for(int i=0;i<tot;i++)
if(col[i]==-1) col[i]=cirnum++;
for(int i=1;i<=m;i++)
{
to
=e[i].v;
e[i].u
=col[e[i].u];
e[i].v
=col[e[i].v];
if(e[i].u!=e[i].v) e[i].w-=in[to];
}
tot
=cirnum;
root
=col[root];
}
return ans;
}
int main()
{
int tot;
int u,v,w,ans;
while(scanf("%d%d",&n,&m)!=EOF)
{
tot
=0;
while(m--)
{
scanf(
"%d%d%d",&u,&v,&w);
if(u!=v)
{
u
++; v++;
e[
++tot].u=u; e[tot].v=v; e[tot].w=w;
}
}
m
=tot;
ans
=directed_MST();
printf(
"%d",ans);
}
}
View Code