2017.1.21总结

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017.1.21总结相关的知识,希望对你有一定的参考价值。

---恢复内容开始---

今天写了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日结束

以上是关于2017.1.21总结的主要内容,如果未能解决你的问题,请参考以下文章

BootStrap有用代码片段(持续总结)

BootStrap实用代码片段(持续总结)

回归 | js实用代码片段的封装与总结(持续更新中...)

查看发票组代码后的总结和有感

VsCode 代码片段-提升研发效率

Python学习总结