zoj 3742 Bellywhite's Algorithm Homework

来源:互联网 发布:ug4数控车床编程 编辑:程序博客网 时间:2024/04/28 05:51

题意:给出一个无向图,n个点m条边,有一些操作:Q +  查询所有正边和        Q -   查询所有负边和         Q A  查询所有边和        C  X  把跟X邻接的边的权值取反。

思路:这题还是蛮经典的,和hdu 4467 Graph挺像的。就是把顶点度数大于sqrt(m)的点单独拿出来处理,其他的点直接暴力修改。用两个值存所有正边和所有负边的和,修改特殊点的时候,只修改和它相连的也是特殊点之间的边的值,和可以通过维护sum[i][2]算出,这个数组是表示和这个特殊点相连的点的边的正边和负边的和。另外用filp[i]标记这个点,当普通点去修改和它相邻的边时,可以通过两个顶点的filp值来得到当前边的正负……


代码:


#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<set>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=50000+10;struct Edge{    int u,v,next;    int w;    Edge (){};    Edge(int uu,int vv,int ww,int nx) {u=uu;v=vv;w=ww;next=nx;}}edges[maxn<<1];int head[maxn],nEdge;int n,m,q,filp[maxn],degree[maxn];ll a[555][555][2],sum[555][2];ll res[2];int hash[maxn],cnt;void AddEdge(int u,int v,int w){    edges[++nEdge]=Edge(u,v,w,head[u]);    head[u]=nEdge;}void Init(){    memset(head,0xff,sizeof(head));    memset(degree,0,sizeof(degree));    memset(hash,0,sizeof(hash));    memset(filp,0,sizeof(filp));    res[0]=res[1]=0;    nEdge=-1;cnt=0;}void precal(){    int lim=(int)sqrt((double)m);    for(int i=1;i<=n;++i)    {        if(degree[i]>lim)        {            hash[i]=++cnt;        }    }    memset(a,0,sizeof(a));    memset(sum,0,sizeof(sum));    int u,v;    for(int i=0;i<nEdge;i+=2)    {        if(edges[i].w>0) res[0]+=edges[i].w;        else res[1]+=edges[i].w;        u=edges[i].u;v=edges[i].v;        if(hash[u]&&hash[v])        {            if(edges[i].w>0)            {                a[hash[u]][hash[v]][0]+=edges[i].w;                a[hash[v]][hash[u]][0]+=edges[i].w;            }            else            {                a[hash[u]][hash[v]][1]+=edges[i].w;                a[hash[v]][hash[u]][1]+=edges[i].w;            }        }        if(hash[u]) sum[hash[u]][edges[i].w<0]+=edges[i].w;        if(hash[v]) sum[hash[v]][edges[i].w<0]+=edges[i].w;    }}void changes(int x){    if(hash[x])    {        res[0]+=(-sum[hash[x]][1]);        res[0]-=sum[hash[x]][0];        res[1]+=(-sum[hash[x]][0]);        res[1]-=sum[hash[x]][1];        swap(sum[hash[x]][0],sum[hash[x]][1]);        sum[hash[x]][0]*=-1;sum[hash[x]][1]*=-1;        for(int i=1;i<=cnt;++i)        {            if(i==hash[x]) continue;            sum[i][0]-=a[i][hash[x]][0];            sum[i][0]+=(-a[i][hash[x]][1]);            sum[i][1]-=a[i][hash[x]][1];            sum[i][1]+=(-a[i][hash[x]][0]);            swap(a[i][hash[x]][0],a[i][hash[x]][1]);            a[i][hash[x]][0]*=-1;a[i][hash[x]][1]*=-1;            swap(a[hash[x]][i][0],a[hash[x]][i][1]);            a[hash[x]][i][0]*=-1;a[hash[x]][i][1]*=-1;        }        filp[x]^=1;    }    else    {        int v,tmp;        filp[x]^=1;        for(int k=head[x];k!=-1;k=edges[k].next)        {            v=edges[k].v;            if(filp[x]^filp[v]) tmp=-edges[k].w;            else tmp=edges[k].w;            if(tmp>0)            {                res[0]+=tmp;                res[1]-=(-tmp);                if(hash[v])                {                    sum[hash[v]][0]+=tmp;                    sum[hash[v]][1]-=(-tmp);                }            }            else            {                res[0]-=(-tmp);                res[1]+=tmp;                if(hash[v])                {                    sum[hash[v]][0]-=(-tmp);                    sum[hash[v]][1]+=tmp;                }            }        }    }}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    char str[5];    //map<ll,int>mp;    int first=true;    while(~scanf("%d%d%d",&n,&m,&q))    {        if(!first) printf("\n");        first=false;        Init();        //mp.clear();        int u,v,w;        for(int i=0;i<m;++i)        {            scanf("%d%d%d",&u,&v,&w);            degree[u]++;degree[v]++;            AddEdge(u,v,w);            AddEdge(v,u,w);            //mp[tmp]=nEdge;        }        precal();        ll ans=0;        int x;        while(q--)        {            scanf("%s",str);            if(str[0]=='Q')            {                scanf("%s",str);                if(str[0]=='A')                    ans=res[0]+res[1];                else if(str[0]=='+')                    ans=res[0];                else ans=res[1];                printf("%lld\n",ans);            }            else            {                scanf("%d",&x);                changes(x);            }        }    }    return 0;}


0 0
原创粉丝点击