2017.1.21总结

来源:互联网 发布:阿里云测试 编辑:程序博客网 时间:2024/05/16 11:24

今天写了2道题,一道p1227 一道p1919

p1227原题:


 

给出一有向图,图中每条边都被标上了关系运算符‘<’,‘>’,‘=’。现在要给图中每个顶点标上一个大于等于0,小于等于k的某个整数使所有边上的符号得到满足。若存在这样的k,则求最小的k,若任何k都无法满足则输出NO。

例如下表中最小的k为2。

结点1>结点2
结点2>结点3
结点2>结点4
结点3=结点4

如果存在这样的k,输出最小的k值;否则输出‘NO’。


 

这道题是差分约束+拓扑排序题目,需要注意的是虽然题目有3种边,但实际上只有2种,只需要把大于边反过来就是小于边,反之亦然

对等于边需要缩为一个点

代码:

复制代码
#include<iostream>#include<string>#include<algorithm>#include<cstring>#include<cstdio>#include<cmath>#include<iomanip>#include<queue>using namespace std;int n,m;int len=0,dis[30000],lin[30000];int id[30000];struct node{    int x,y,v;}e[30000];void init(int xx,int yy,int vv){    e[++len].y=lin[xx];lin[xx]=len;e[len].x=yy;e[len].v=vv;}bool pai(){    /*memset(dis,0,sizeof(dis));*/    int q[30000];    int head=0,tail=0;    int maxx=0;    for(int i=1;i<=n;i++)        if(id[i]==0)    q[++tail]=i;    while(head<=tail)    {        int tn=q[++head];        int te=lin[tn];        for(int i=te;i;i=e[i].y)        {            int tmp=e[i].x;            id[tmp]--;            if(id[e[i].x]<0)                return 1;            dis[tmp]=max(dis[tmp],dis[q[head]]+e[i].v);            if(id[e[i].x]==0)                q[++tail]=e[i].x;        }    }    sort(dis+1,dis+1+n);    if(dis[n]<=maxx)        return 1;    return 0;}int main(){    //freopen("2.in","r",stdin);    //freopen("2.out","w",stdout);    //ios::sync_with_stdio(false);    cin>>n>>m;    memset(e,0,sizeof(e));    memset(id,0,sizeof(id));    /*for(int i=1;i<=n;i++)        init(0,i,0);*/    for(int i=1;i<=m;i++)    {        int xx,yy,vv;        cin>>xx>>yy>>vv;        if(vv==0)        {            init(xx,yy,0);            id[yy]++;        }        else if(vv==1)        {            init(yy,xx,1);            id[xx]++;        }        else if(vv==-1)        {            init(xx,yy,1);            id[yy]++;        }    }    if(pai())        cout<<"NO"<<endl;    else    {        cout<<dis[n]<<endl;    }    return 0;}
复制代码

 

p1919题目


 

Farmer John有B头奶牛 (1 <= B <= 25,000). 有 N (2*B <= N <= 50,000) 个农场,编号1..N,有 M (N-1 <= M <= 100,000) 条双向边. 第i条边连接农场R_i 和S_i (1 <= R_i <= N; 1 <= S_i<= N) ,该边长度是L_i (1 <= L_i <= 2,000).

居住农场P_i的奶牛A (1 <= P_i <= N),它想送一份新年礼物给居住在农场 Q_i (1 <= Q_i <= N)的奶牛B,但是奶牛A必须先到FJ(居住在编号1的农场)那里取礼物,然后再送给奶牛B. 你的任务是:奶牛A至少需要走多远的路程?


 

这道题其实就是一个裸的spfa,但是!我做这道题的时候出了一个致命失误,使用spfa时数组要开成双倍,然而我并没有那样做,结果先是RE,一通瞎改后是TLE,一通瞎改然后是WA,简直了,最后我还是看了别人的代码才发现我的错误,然后就过了,这给我一个教训:永远不要吝惜评测机的内存,只要不超范围,随便用啦

代码:

复制代码
//2017.1.21 Earl_WR#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;struct edge{    int v,next,y;}e[200010]={};long long lin[200010]={};long long l=0;long long dis[200010]={},vis[200010]={},queue[200010]={},head=0,tail=1,n,m,b;long long result=0;long long insert(int xx,int yy,int vv){    e[++l].next=lin[xx];lin[xx]=l;    e[l].y=yy;e[l].v=vv;}long long read(){    long long x=0,f=1;char ch=getchar();    while (ch<'0' || ch>'9'){if (ch=='-')f=-1;ch=getchar();}    while (ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}void in(){    //freopen ("test.in","r",stdin);    //freopen ("test.out","w",stdout);    n=read();m=read();b=read();    for (long long i=1;i<=m;i++)    {        long long x,y,z;        x=read();y=read();z=read();        insert(x,y,z);        insert(y,x,z);    }}void spfa(long long s){    memset(dis,10,sizeof(dis));    memset(vis,0,sizeof(vis));    dis[s]=0;vis[s]=1;queue[1]=s;    head=0;tail=1;    while (head<tail)    {        long long tn=queue[++head];vis[tn]=0;        long long te=lin[tn];        for (int i=te;i;i=e[i].next)        {            int temp=e[i].y;            if (dis[tn]+e[i].v<dis[temp])            {                dis[temp]=dis[tn]+e[i].v;                if (!vis[temp])                {                    queue[++tail]=temp;                    vis[temp]=1;                }            }        }    }}int main(){    in();    spfa(1);    for (int i=1;i<=b;i++)    {        long long start=read(),end=read();        result=dis[start]+dis[end];        cout<<result<<endl;    }    return 0;}
复制代码

以上,1月21日结束

0 0
原创粉丝点击