hdu 4858 專案管理 (圖的分治)

來源:互聯網
上載者:User

標籤:des   style   java   color   strong   os   

專案管理Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 252    Accepted Submission(s): 88

Problem Description我們建造了一個大項目!這個項目有n個節點,用很多邊串連起來,並且這個項目是連通的!
兩個節點間可能有多條邊,不過一條邊的兩端必然是不同的節點。
每個節點都有一個能量值。

現在我們要編寫一個專案管理軟體,這個軟體呢有兩個操作:
1.給某個項目的能量值加上一個特定值。
2.詢問跟一個項目相鄰的項目的能量值之和。(如果有多條邊就算多次,比如a和b有2條邊,那麼詢問a的時候b的權值算2次)。
 
Input第一行一個整數T(1 <= T <= 3),表示測試資料的個數。
然後對於每個測試資料,第一行有兩個整數n(1 <= n <= 100000)和m(1 <= m <= n + 10),分別表示點數和邊數。

然後m行,每行兩個數a和b,表示a和b之間有一條邊。
然後一個整數Q。

然後Q行,每行第一個數cmd表示操作類型。如果cmd為0,那麼接下來兩個數u v表示給項目u的能量值加上v(0 <= v <= 100)。
如果cmd為1,那麼接下來一個數u表示詢問u相鄰的項目的能量值之和。

所有點從1到n標號。 
Output對每個詢問,輸出一行表示答案。 
Sample Input
13 21 21 360 1 150 3 41 11 30 2 331 2
 
Sample Output
41515
 
思路:如果直接暴力,原則上是要TLE的,可惜這題資料比較水~下面說說我的解法每個點維護兩個值,w[i]-該點的值、sum[i]-相鄰節點值的和。怎樣在複雜度較小的範圍內維護這兩個值呢。如果把與x相連的點分為兩類,一類的度數大於它(該類不超過(2m)^(1/2)),另一類度數小於它。更新和查詢時時只操作度數大於它的點,就能降低複雜度了。
一個點更新時度數大於它的相鄰點是直接更新了的,查詢大點時答案已經統計了,但是查詢小點的時候答案這沒有統計完,對於小點,這個點又為小點的大點,於是再遍曆一下,將未更新的點更新維護sum數組即可。
複雜度就為 q*sqrt(m)了。還有注意要將重邊合并。
代碼:
#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#define maxn 100005#define MAXN 300005using namespace std;int n,m,ans,cnt,tot;int head[maxn],dug[maxn];int sum[maxn],w[maxn];struct node{    int u,v,num;} edge[MAXN];struct Node{    int v,next,num,last;} g[MAXN];void addedge(int u,int v,int num){    cnt++;    g[cnt].v=v;    g[cnt].num=num;    g[cnt].next=head[u];    head[u]=cnt;}bool cmp(node xx,node yy){    if(xx.u!=yy.u) return xx.u<yy.u ;    if(xx.v!=yy.v) return xx.v<yy.v;}int main(){    int i,j,t,u,v;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        for(i=1; i<=n; i++) dug[i]=head[i]=w[i]=sum[i]=0;        for(i=1; i<=m; i++)        {            scanf("%d%d",&u,&v);            if(u>v) swap(u,v);            edge[i].u=u;            edge[i].v=v;            edge[i].num=1;        }        sort(edge+1,edge+m+1,cmp);        tot=1;        for(i=2; i<=m; i++)  // 合并相同邊        {            if(edge[i].u==edge[tot].u&&edge[i].v==edge[tot].v) edge[tot].num++;            else edge[++tot]=edge[i];        }        for(i=1; i<=tot; i++) // 計算度數        {            dug[edge[i].u]++; dug[edge[i].v]++;        }        cnt=0;        for(i=1; i<=tot; i++) // 點與相鄰節點度數較大的點建圖        {            u=edge[i].u;            v=edge[i].v;            if(dug[v]>dug[u]) addedge(u,v,edge[i].num);            else addedge(v,u,edge[i].num);        }        int q,op,val;        scanf("%d",&q);        while(q--)        {            scanf("%d",&op);            if(op==0)            {                scanf("%d%d",&u,&val);                w[u]+=val;                for(i=head[u]; i; i=g[i].next)  // 更新大點的sum值                {                    v=g[i].v;                    sum[v]+=g[i].num*val;                }            }            else            {                scanf("%d",&u);                ans=sum[u];                for(i=head[u]; i; i=g[i].next) // 計算未更新的大點的值                {                    v=g[i].v;                    if(g[i].last!=w[v])                    {                        ans+=g[i].num*(w[v]-g[i].last);                        g[i].last=w[v];                    }                }                sum[u]=ans;                printf("%d\n",ans);            }        }    }    return 0;}




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.