作为退役菜鸡,在队内不负责图论部分,所以图论部分菜之又菜。现在单挑时遇到图论的题只能自认倒霉,做不出来呀!
痛定思痛!决心好好学习图论!
首先是Dijkstra、Floyd、Prmie、Kruskal、拓扑排序,这怎么可能不会呢~~so直接跳过
先学个匈牙利算法
(解二分图最大匹配)
洛谷:【模板】二分图最大匹配
int m,n,e;
vector<int>vec[maxn];
bool vs[maxn];
int match[maxn];
queue<int>q;
bool dfs(int x)
{
for(int j:vec[x])
{
if(vs[j])continue;
vs[j]=1;q.push(j);
if(!match[j]||dfs(match[j]))
{
match[j]=x;
return 1;
}
}
return 0;
}
void solve()
{
scanf("%d%d%d",&n,&m,&e);
for(int i=1;i<=e;i++)
{
int u,v;
scanf("%d%d",&u,&v);
v+=n;
vec[u].pb(v);
vec[v].pb(u);
}
int ans=0;
for(int i=1;i<=n;i++)
{
while(!q.empty())vs[q.front()]=0,q.pop();
ans+=dfs(i);
}
printf("%d\n",ans);
}
int m,n;
vector<int>vec[maxn];
bool vs[maxn];
int match[maxn];
queue<int>q;
bool dfs(int x)
{
for(int j:vec[x])
{
if(vs[j])continue;
vs[j]=1;q.push(j);
if(!match[j]||dfs(match[j]))
{
match[j]=x;
return 1;
}
}
return 0;
}
void solve()
{
scanf("%d%d",&m,&n);
n-=m;
int u,v;
while(scanf("%d%d",&u,&v)&&u!=-1)
{
vec[u].pb(v);
vec[v].pb(u);
}
int ans=0;
for(int i=1;i<=m;i++)
{
while(!q.empty())vs[q.front()]=0,q.pop();
ans+=dfs(i);
}
printf("%d\n",ans);
for(int i=m+1;i<=m+n;i++)
{
if(match[i])printf("%d %d\n",i,match[i]);
}
}
接下来就是KM算法啦
(解二分图最大匹配中的最大权值和)
HDU2255奔小康赚大钱
int n;
int v[maxn][maxn];
bool vx[maxn],vy[maxn];
int match[maxn],mi;
int wx[maxn],wy[maxn];
bool dfs(int x)
{
vx[x]=1;
for(int i=1;i<=n;i++)
{
if(vy[i])continue;
int tmp=wx[x]+wy[i]-v[x][i];
if(tmp==0)
{
vy[i]=1;
if(!match[i]||dfs(match[i]))
{
match[i]=x;
return 1;
}
}
else if(tmp>0)
{
mi=min(mi,tmp);
}
}
return 0;
}
void solve()
{
memset(wx,0,sizeof wx);
memset(wy,0,sizeof wy);
memset(match,0,sizeof match);
memset(vx,0,sizeof vx);
memset(vy,0,sizeof vy);
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
{
scanf("%d",&v[i][j]);
wx[i]=max(wx[i],v[i][j]);
}
for(int i=1;i<=n;i++)
{
while(1)
{
memset(vx,0,sizeof vx);
memset(vy,0,sizeof vy);
mi=1e9;
if(dfs(i))break;
for(int j=1;j<=n;j++)
{
if(vx[j])wx[j]-=mi;
if(vy[j])wy[j]+=mi;
}
}
}
int ans=0;
for(int i=1;i<=n;i++)ans+=v[match[i]][i];
printf("%d\n",ans);
}
int main()
{
int T=1;
// scanf("%d",&T);
// while(T--)solve();
while(~scanf("%d",&n))solve();
}
int n,c[maxn][maxn];
bool vx[maxn],vy[maxn];
int match[maxn];
int wx[maxn],wy[maxn],mi=1e9;
bool dfs(int x)
{
vx[x]=1;
for(int i=1;i<=n;i++)
{
if(vy[i])continue;
int tmp=wx[x]+wy[i]-c[x][i];
if(!tmp)
{
vy[i]=1;
if(!match[i]||dfs(match[i]))
{
match[i]=x;
return 1;
}
}
else if(tmp>0)
{
mi=min(mi,tmp);
}
}
return 0;
}
int KM()
{
for(int i=1;i<=n;i++)
{
while(1)
{
memset(vx,0,sizeof vx);
memset(vy,0,sizeof vy);
if(dfs(i))break;
for(int j=1;j<=n;j++)
{
if(vx[j])wx[j]-=mi;
if(vy[j])wy[j]+=mi;
}
}
}
int ans=0;
for(int i=1;i<=n;i++)ans+=c[match[i]][i];
return ans;
}
void solve()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
{
scanf("%d",&c[i][j]);
wx[i]=max(wx[i],c[i][j]);
}
int ans1=KM();
memset(wy,0,sizeof wy);
for(int i=1;i<=n;i++)
{
wx[i]=-1e9;
for(int j=1;j<=n;j++)
{
c[i][j]*=-1;
wx[i]=max(wx[i],c[i][j]);
}
}
memset(match,0,sizeof match);
mi=1e9;
int ans2=-KM();
printf("%d\n%d\n",ans2,ans1);
}
有向图缩点tarjan
int n,m,a[maxn],num,ans;
vector<int>vec[maxn];
int dfn[maxn],low[maxn],cnt;
bool vis[maxn];
int sta[maxn],stk;
int be[maxn],val[maxn],in[maxn],ma[maxn];
int u[maxn],v[maxn];
void tarjan(int x)
{
dfn[x]=low[x]=++cnt;
sta[++stk]=x;
vis[x]=1;
for(int j:vec[x])
{
if(!dfn[j])
{
tarjan(j);
low[x]=min(low[x],low[j]);
}
else if(vis[j])
{
low[x]=min(low[x],low[j]);
}
}
if(dfn[x]==low[x])
{
++num;
while(1)
{
int y=sta[stk--];
be[y]=num;
val[num]+=a[y];
vis[y]=0;
if(x==y)break;
}
}
}
void topu()
{
queue<int>q;
for(int i=1;i<=n;i++)if(!in[i])q.push(i);
while(!q.empty())
{
int p=q.front();q.pop();
val[p]+=ma[p];
ans=max(ans,val[p]);
for(int j:vec[p])
{
in[j]--;
ma[j]=max(ma[j],val[p]);
if(!in[j])q.push(j);
}
}
}
void solve()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u[i],&v[i]);
vec[u[i]].pb(v[i]);
}
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
for(int i=1;i<=n;i++)vec[i].clear();
for(int i=1;i<=m;i++)
{
if(be[u[i]]==be[v[i]])continue;
vec[be[u[i]]].pb(be[v[i]]);
in[be[v[i]]]++;
}
topu();
printf("%d\n",ans);
}