通讯(tarjan缩点)(20190716NOIP模拟测试4)
B. 通讯
题目描述
输入格式
输出格式
样例
数据范围与提示
水题
tarjan缩点,贪心找每个点的最小入边即可(我用dfs实现,本质都是贪心)
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 using namespace std; 5 int n,m,dfn[51000],low[51000],num,st[51000],sp[51000],ins[51000],mi[51000],v[51000],cnt; 6 struct node{ 7 int ver,len; 8 }; 9 vector<node>to[51000],son[51000]; 10 void tarjan(int x){ 11 dfn[x]=low[x]=++num; 12 st[++st[0]]=x; 13 ins[x]=1; 14 //sort(to[x].begin(),to[x].end(),cmp); 15 for(int i=0;i<to[x].size();i++){ 16 node w=to[x][i]; 17 if(!dfn[w.ver]){ 18 tarjan(w.ver); 19 low[x]=min(low[x],low[w.ver]); 20 } 21 else if(ins[w.ver]) low[x]=min(low[x],dfn[w.ver]); 22 } 23 if(low[x]==dfn[x]){ 24 cnt++; 25 int y; 26 do{ 27 y=st[st[0]--]; 28 ins[y]=0; 29 sp[y]=cnt; 30 }while(y!=x); 31 32 } 33 } 34 long long dfs(int x){ 35 v[x]=1; 36 long long cet=0; 37 //sort(son[x].begin(),son[x].end(),cmp); 38 // cout<<x<<" "<<son[x].size()<<endl; 39 for(int i=0;i<son[x].size();i++){ 40 node w=son[x][i]; 41 //cout<<w.ver<<" "<<w.len<<endl; 42 if(v[w.ver]){ 43 if(mi[w.ver]>w.len){ 44 cet-=(mi[w.ver]-w.len); 45 mi[w.ver]=w.len; 46 } 47 continue; 48 } 49 cet+=dfs(w.ver); 50 cet+=w.len; 51 52 mi[w.ver]=w.len; 53 } 54 ///cout<<cet<<endl; 55 return cet; 56 57 } 58 int main(){ 59 scanf("%d%d",&n,&m); 60 while(n!=0||m!=0){ 61 int x; 62 for(int i=1;i<=m;i++){ 63 node w; 64 scanf("%d%d%d",&x,&w.ver,&w.len); 65 w.ver++; 66 to[x+1].push_back(w); 67 } 68 // for(int i=1;i<=n;i++) cout<<i<<" "<<to[i].size()<<endl; 69 for(int i=1;i<=n;i++) 70 if(!dfn[i]) tarjan(i); 71 //for(int i=1;i<=n;i++) cout<<i<<" "<<to[i].size()<<endl; 72 for(int i=1;i<=n;i++){ 73 //cout<<i<<" "<<sp[i]<<" "<<to[i].size()<<endl; 74 for(int j=0;j<to[i].size();j++){ 75 node w=to[i][j]; 76 if(sp[i]!=sp[w.ver]){ 77 w.ver=sp[w.ver]; 78 son[sp[i]].push_back(w); 79 } 80 } 81 } 82 /*for(int i=1;i<=cnt;i++){ 83 cout<<i<<" "<<son[i].size()<<endl; 84 for(int j=0;j<son[i].size();j++){ 85 printf("%d %d %d\n",i,son[i][j].ver,son[i][j].len); 86 } 87 }*/ 88 long long ans=dfs(sp[1]); 89 printf("%lld\n",ans); 90 for(int i=1;i<=n;i++){ 91 dfn[i]=low[i]=v[i]=sp[i]=mi[i]=v[i]=0; 92 to[i].clear(); 93 son[i].clear(); 94 num=0; 95 cnt=0; 96 } 97 scanf("%d%d",&n,&m); 98 } 99 100 }
我的tarjan+dfs代码
天皇skyh的贪心找小边
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define db(x) cerr<<#x<<"="<<x<<endl 5 #define cl(x) memset(x,0,sizeof(x)) 6 using namespace std; 7 const int N=50100,M=501000; 8 int n,m,scc; 9 int tot,head[N],to[M],nxt[M],w[M]; 10 int top,stack[N],dfn[N],low[N],num,bl[N]; 11 bool instack[N]; 12 int imin[N]; 13 void tarjan(int x) 14 { 15 dfn[x]=low[x]=++num; 16 stack[++top]=x; instack[x]=1; 17 for(int i=head[x];i;i=nxt[i]) 18 { 19 int y=to[i]; 20 if(!dfn[y]) 21 { 22 tarjan(y); 23 low[x]=min(low[x],low[y]); 24 } 25 else if(instack[y]) low[x]=min(low[x],dfn[y]); 26 } 27 if(dfn[x]==low[x]) 28 { 29 ++scc; int y; 30 do{ 31 y=stack[top--]; 32 bl[y]=scc; 33 instack[y]=0; 34 }while(y!=x); 35 } 36 } 37 int main() 38 { 39 while(scanf("%d%d",&n,&m)==2&&(n||m)) 40 { 41 cl(dfn); cl(head); 42 memset(imin,0x3f,sizeof(imin)); 43 tot=0; top=0; num=0; scc=0; 44 for(int i=1,a,b,d;i<=m;i++) 45 { 46 scanf("%d%d%d",&a,&b,&d); 47 a++; b++; 48 to[++tot]=b; w[tot]=d; 49 nxt[tot]=head[a]; head[a]=tot; 50 } 51 tarjan(1); 52 //db(scc); 53 for(int i=1;i<=n;i++) 54 for(int j=head[i];j;j=nxt[j]) 55 { 56 int y=to[j]; 57 if(bl[i]==bl[y]) continue; 58 imin[bl[y]]=min(imin[bl[y]],w[j]); 59 } 60 long long ans=0; 61 for(int i=1;i<=scc;i++) 62 if(imin[i]<=10000000) 63 ans+=imin[i]; 64 printf("%lld\n",ans); 65 } 66 return 0; 67 }