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总结的主要内容,如果未能解决你的问题,请参考以下文章