下午居然没做出这题,我傻了。。。一直在用我不熟悉的网络流在搞 网上也有人用最小树形图做
/**//* 题意:给出一个有向图,a传到b的代价为c,同一个环内的传输不用代价 求从一个点传到所有点的最小代价 先强连通缩点 找到入度为0的点作为原点 然后用spfa更新即可 更新的规则是 if(dist[v]>g[u][v])dist[v]=g[u][v] 方正最后每个点都被传到,究竟它被谁传过来的呢? 肯定是被花费最小的那条边传过来的 这样子一直更新下去肯定是最优值! 两种实现,用spfa也行 更直接的两重循环找每个点的父边中的最小值 */ #include<cstdio> #include<cstring> #include<vector> #include<algorithm> #include<queue> using namespace std;
const int MAXN = 50000; const int INF = 1000000000;
struct Edge { int v,w; Edge *next; }edge[100000*2+10],*E[MAXN+10],*_E[MAXN+10],*pE;
struct Graph { vector<int>G[200]; int SCC,n; int ord[MAXN+10],ID[MAXN+10]; int g[200][200]; int ind[200],dist[200],in[200];
void init(int nn) { n=nn; memset(E,0,sizeof(E)); memset(_E,0,sizeof(_E)); pE=edge; } void add(int u,int v,int w) { pE->v=v; pE->w=w; pE->next=E[u]; E[u]=pE++;
pE->v=u; pE->w=w; pE->next=_E[v]; _E[v]=pE++; } void dfs1(int u) { ID[u]=1; for(Edge *it=_E[u];it;it=it->next) { if(ID[it->v]==-1)dfs1(it->v); } ord[SCC++]=u; } void dfs2(int u) { ID[u]=SCC; for(Edge *it=E[u];it;it=it->next) if(ID[it->v]==-1)dfs2(it->v); } void kosaraju() { SCC=0; memset(ID,-1,sizeof(ID)); for(int i=0;i<n;i++) if(ID[i]==-1)dfs1(i); SCC=0; memset(ID,-1,sizeof(ID)); for(int i=n-1;i>=0;i--) if(ID[ord[i]]==-1) { dfs2(ord[i]); SCC++; } } void build() { for(int i=0;i<SCC;i++) for(int j=0;j<SCC;j++) g[i][j]=INF; for(int i=0;i<n;i++) for(Edge *it=E[i];it;it=it->next) { if(ID[i]==ID[it->v])continue; if(it->w<g[ID[i]][ID[it->v]])g[ID[i]][ID[it->v]]=it->w; }
for(int i=0;i<SCC;i++)G[i].clear(); memset(ind,0,sizeof(ind)); for(int i=0;i<SCC;i++) for(int j=0;j<SCC;j++) if(g[i][j]!=INF) { G[i].push_back(j); ind[j]++; } } int cal2()//对每个点,在其邻接矩阵中找父边中的最小值 { int ans = 0; for(int j=0;j<SCC;j++) { int Min=INF; for(int i=0;i<SCC;i++) if(Min>g[i][j])Min=g[i][j]; if(Min!=INF)ans+=Min; } return ans; } int cal1() { int s; for(int i=0;i<SCC;i++) { dist[i]=INF; if(ind[i]==0)s=i; } dist[s]=0; memset(in,0,sizeof(in)); in[s]=1; queue<int>Q; Q.push(s); while(!Q.empty()) { int u=Q.front();Q.pop(); for(int i=0,size=G[u].size();i<size;i++) { int v=G[u][i]; if(dist[v]>g[u][v]) { dist[v]=g[u][v]; if(in[v]==0) { in[v]=1; Q.push(v); } } } } int ans = 0; for(int i=0;i<SCC;i++) { ans+=dist[i]; } return ans; } }graph; int main() { //freopen("in","r",stdin); int n,m; while(~scanf("%d%d",&n,&m)) { graph.init(n); for(int i=0;i<m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); graph.add(a,b,c); } graph.kosaraju(); graph.build(); //printf("%d\n",graph.cal1()); printf("%d\n",graph.cal2()); } return 0; }
|
|
常用链接
随笔分类
Links
搜索
最新评论
|
|