【數據范圍】
對於30%的數據,保證 1<=N<=2000
對於100%的數據,保證 1<=N<=100000
對於所有的數據,保證 1<=M<=1000000,1<=Hi<=1000000000,1<=Ki<=1000000000。
媽的BZOJ坑啊,M的數據范圍是[1,2000000],坑死我N次了
第一問BFS很明顯不解釋,第二問是最小樹形圖。。。但是這題是有向圖又不好做,最小生成樹只能對付無向圖,可題目范圍大得嚇人,還是用kruscal,只對可以和起點聯通的邊跑kruscal,邊的預處理就對邊的高度(這裡看邊的終點高度,因為終點高度小於起點高度)降序排序,高度相同時就按邊權升序排序,kruscal就ok了
很令人費解的是為什麼邊兩端高度相同時要建雙向邊呢,難道一個路沒坡的話還能滑?真是奇怪,在這裡也被狠狠地坑了下
//題目大意:求有向圖的最小生成樹 #include#include #include #include #include #define MAXN 100050 #define MAXM 2000050 using namespace std; struct Line { int u,v; //起點、終點 int w; //邊權 int next; //下一條邊 }edge[MAXM]; //邊集 queue q; //bfs用隊列 int f[MAXN]; //並查集用 long long int dis=0; //dis=最短距離 int n,m,cnt=0,tot=0,visit[MAXN],high[MAXN]; //cnt=可經過的點總數,tot=有效邊的總數,visit[i]=1表示點i訪問過,high[i]=點i的高度 int head[MAXM]; int cmp(Line a,Line b) //先按邊的終點高度降序排序,高度相同的按邊權升序排序 { return high[b.v] t,邊權為n { edge[tot].u=s; edge[tot].v=t; edge[tot].w=n; edge[tot].next=head[s]; head[s]=tot++; } void init() { int i,j; memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%d",&high[i]); for(i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); if(high[u]>=high[v]) AddLine(u,v,w); //加邊 if(high[v]>=high[u]) AddLine(v,u,w); } } void bfs() //bfs找可走的路 { int i,x; q.push(1); visit[1]=1; //非常重要!!! while(!q.empty()) { x=q.front(); q.pop(); cnt++; for(i=head[x];i!=-1;i=edge[i].next) { int y=edge[i].v; //下一條邊的終點 if(!visit[y]) { visit[y]=1; q.push(y); //若該點未被訪問過,標記,入隊 } } } } void kruscal() //kruscal求最小生成樹 { int i,j,rootu,rootv,u,v; sort(edge,edge+tot,cmp); for(i=1;i<=n;i++) f[i]=i; //並查集初始化 for(i=0;i