题意如标题所述,

先无向图缩点,统计出每个bcc权,建新图,然后一遍dfs生成树,标记出每个点(新图)以及其子孙的权值之和。这样之后就可以dfs2来枚举边(原图的桥),更新最小即可。

调试了半天!原来是建老图时候链式前向星和新图的vector<vector< int>>俩种存图搞乱了!!!不可原谅!哎!愚蠢!愚不可及!提交后1A。

后来百度之后,发现说是用树形dp,看了代码解法,竟然和我的是一样的算法。。原来这种算法可以叫树形dp。。。的确有点dp味道。。不过感觉不太浓。。

以后多个图,多种储存方式要分清!e[i][j]!!!e[u][i]\e[j][1]。。。

#include<iostream>
#include<cstdio>
#include<stack>
#include<vector>
#include<cstring>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxv=10010,maxe=50000;
int head[maxv];int nume=0;int e[maxe][2];
void inline adde(int i,int j)
{
e[nume][0]=j;e[nume][1]=head[i];head[i]=nume++;
e[nume][0]=i;e[nume][1]=head[j];head[j]=nume++;
}
int dfn[maxv];int low[maxv];int vis[maxv];int bcc[maxv];int ins[maxv];stack<int>sta;
int times=0; int numb=0; int vise[maxe];
int wi[maxv]; int sumwi[maxv];
void tarjan(int u)
{
dfn[u]=low[u]=times++;
ins[u]=1;
sta.push(u);
for(int i=head[u];i!=-1;i=e[i][1])
{
if(vise[i])continue;
int v=e[i][0];
if(!vis[v])
{
vis[v]=1;
vise[i]=vise[i^1]=1;
tarjan(v);
if(low[v]<low[u])low[u]=low[v];
}
else if(ins[v]&&dfn[v]<low[u])
low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
numb++;
int cur;
do{
cur=sta.top();
sta.pop();
ins[cur]=0;
bcc[cur]=numb;
sumwi[numb]+=wi[cur];
}while(cur!=u);
}
}
vector<vector<int> >e2(maxv+1);
int n,m; int mindis=inf;
int getabs(int x)
{
return x<0?-x:x;
}
void init()
{
numb=times=nume=0;mindis=inf;
memset(vise,0,sizeof(vise));
for(int i=0;i<maxv;i++)
{
sumwi[i]=wi[i]=bcc[i]=ins[i]=dfn[i]=low[i]=vis[i]=0;
e2[i].clear(); head[i]=-1;
}
}
int dfs(int u) //获得sumwi【i】:子孙包括自己的权值和
{
for(int i=0;i<e2[u].size();i++)
{
int v=e2[u][i];
if(!vis[v])
{
vis[v]=1;
sumwi[u]+=dfs(v);
}
}
return sumwi[u];
}
void dfs2(int u)
{
for(int i=0;i<e2[u].size();i++)
{
int v=e2[u][i];
if(!vis[v])
{
if(getabs(sumwi[1]-sumwi[v]-sumwi[v])<mindis)
{
mindis=getabs(sumwi[1]-sumwi[v]-sumwi[v]);
}
vis[v]=1;
dfs2(v);
}
}
}
void solve()
{
vis[0]=1;
tarjan(0);
if(numb==1)
{
printf("impossible\n");
return ;
}
memset(vise,0,sizeof(vise));
for(int i=0;i<n;i++)
for(int j=head[i];j!=-1;j=e[j][1])
if(bcc[i]!=bcc[e[j][0]]&&vise[j]==0)
{
e2[bcc[i]].push_back(bcc[e[j][0]]);
e2[bcc[e[j][0]]].push_back(bcc[i]);
vise[j]=vise[j^1]=1;
}
memset(vis,0,sizeof(vis));
vis[1]=1;
dfs(1);
memset(vis,0,sizeof(vis));
vis[1]=1;
dfs2(1);
printf("%d\n",mindis);
}
void readin()
{
for(int i=0;i<n;i++)
scanf("%d",&wi[i]);
int aa,bb;
for(int i=0;i<m;i++)
{
scanf("%d%d",&aa,&bb);
adde(aa,bb);
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
readin();
solve();
}
return 0;
}

最新文章

  1. javascript运行机制
  2. ZOJ 3481. Expand Tab
  3. PHP自学链接收藏
  4. Java设计模式(七) 模板模式-使用钩子
  5. [原]Wpf应用Path路径绘制圆弧
  6. EasyUI-datagrid-自动合并单元格(转)
  7. Linux安全运维日志排查几个 tips
  8. PHP得出附件扩展名
  9. 第一章 Slenium2-Java 自动化测试基础
  10. POPTEST老李分享session,cookie的安全性以及区别 2
  11. Android之Material Dialogs详解
  12. kubernetes安装
  13. while循环 格式化输出 运算符 编码
  14. webpack4 系列教程(六): 处理SCSS
  15. SpringBoot Mybatis 分页插件PageHelper
  16. Roslyn研究随笔
  17. phpadmin登录报错:#1045 - Access denied for user &#39;root&#39;@&#39;localhost&#39; (using password: yes)
  18. grep命令与正则表达式
  19. 机器学习 数据预处理之独热编码(One-Hot Encoding)
  20. margin 负边距应用

热门文章

  1. Python中字符串String的基本内置函数与过滤字符模块函数的基本用法
  2. 初学js之多组图片切换实例
  3. 动态规划:ZOJ1074-最大和子矩阵 DP(最长子序列的升级版)
  4. LA_3942 LA_4670 从字典树到AC自动机
  5. Monkey&#160;log分析说明
  6. CSU-1974 神奇药水
  7. 平时代码中不符合python风格的举例
  8. vivo和OPPO手机刷机
  9. MySQL误操作后如何快速恢复数据?
  10. Ubuntu下建立Pycharm快捷方式