Candies(差分约束)

http://poj.org/problem?id=3159

题意:

flymouse是幼稚园班上的班长,一天老师给小朋友们买了一堆的糖果,由flymouse来分发,在班上,
flymouse和snoopy是死对头,两人势如水火,不能相容,因此fly希望自己分得的糖果数尽量多于
snoopy,而对于其他小朋友而言,则只希望自己得到的糖果不少于班上某某其他人就行了。

比如A小朋友强烈希望自己的糖果数不能少于B小朋友m个,即B- A<=m,A,B分别为
A、B小朋友的分得的糖果数。这样给出若干组这样的条件,要使fly最后分得的糖果数s1和snoopy
最后分得的糖果数s2差别取到最大!即s2-s1取最大.

思路:求源点1到n的最短距离。Dijstra+邻接表

不过直接用dij会超时。可以用优先队列优化一下。不过运算符重载那里被卡了好久。悲惨的教训啊。

 1 #include<stdio.h>

 2 #include<string.h>

 3 #include<queue>

 4 using namespace std;

 5 

 6 const int INF = 0x3f3f3f3f;

 7 const int maxv = 30100;

 8 const int maxe = 150100;

 9 struct node

10 {

11     int v,w,next;

12 }edge[maxe];//邻接表

13 

14 struct node1

15 {

16     int v,c;

17     bool operator < (const node1 &t) const

18     {

19         return c > t.c;//距离从小到大排序

20     }

21 };//存每个节点和它到源点的最短距离。

22 

23 int n,m,cnt;

24 int p[maxe];

25 int dis[maxv];

26 int vis[maxv];

27 void add(int u, int v, int w)

28 {

29     cnt++;

30     edge[cnt].v = v;

31     edge[cnt].w = w;

32     edge[cnt].next = p[u];

33     p[u] = cnt;

34 }

35 

36 void dijstra(int s)

37 {

38     priority_queue<struct node1> que;

39     for(int i = 1; i <= n; i++)

40         dis[i] = INF;

41     memset(vis,0,sizeof(vis));

42 

43     dis[s] = 0;

44     que.push((struct node1){s,dis[s]});

45     for(int i = 0; i < n; i++)

46     {

47         while(!que.empty() && vis[que.top().v])

48             que.pop();

49         if(que.empty()) break;

50 

51         node1 tmp = que.top();

52         que.pop();

53         vis[tmp.v] = 1;

54         for(int j = p[tmp.v]; j; j = edge[j].next)

55         {

56             if((dis[edge[j].v] > dis[tmp.v] + edge[j].w) && !vis[edge[j].v])

57             {

58                 dis[edge[j].v] = dis[tmp.v] + edge[j].w;

59                 que.push((struct node1){edge[j].v,dis[edge[j].v]});

60             }

61         }

62     }

63 }

64 

65 int main()

66 {

67     while(~scanf("%d %d",&n,&m))

68     {

69         int u,v,w;

70         memset(p,0,sizeof(p));

71         cnt = 0;

72         for(int i = 0; i < m; i++)

73         {

74             scanf("%d %d %d",&u,&v,&w);

75             add(u,v,w);

76         }

77         dijstra(1);

78         printf("%d\n",dis[n]);

79 

80     }

81     return 0;

82 }
View Code

 看discuss里面也可以用SPFA+stack,可能用stack效率高一点吧。

 1 #include<stdio.h>

 2 #include<string.h>

 3 #include<algorithm>

 4 #include<stack>

 5 using namespace std;

 6 

 7 const int INF = 0x3f3f3f3f;

 8 const int maxv = 30100;

 9 const int maxe = 150100;

10 

11 struct node

12 {

13     int v,w;

14     int next;

15 }edge[maxe];

16 int n,m,cnt;

17 int p[maxe];

18 int dis[maxv],instack[maxv];

19 void add(int u, int v, int w)

20 {

21     cnt++;

22     edge[cnt].v = v;

23     edge[cnt].w = w;

24     edge[cnt].next = p[u];

25     p[u] = cnt;

26 }

27 

28 void SPFA(int s)

29 {

30     stack<int>st;

31     for(int i = 1; i <= n; i++)

32         dis[i] = INF;

33     memset(instack,0,sizeof(instack));

34     dis[s] = 0;

35     st.push(s);

36     instack[s] = 1;

37     while(!st.empty())

38     {

39         int u = st.top();

40         st.pop();

41         instack[u] = 0;

42 

43         for(int i = p[u]; i; i = edge[i].next)

44         {

45             if(dis[edge[i].v] > dis[u] + edge[i].w)

46             {

47                 dis[edge[i].v] = dis[u] + edge[i].w;

48                 if(!instack[edge[i].v])

49                 {

50                     st.push(edge[i].v);

51                     instack[edge[i].v] = 1;

52                 }

53             }

54         }

55     }

56 }

57 

58 int main()

59 {

60     while(~scanf("%d %d",&n,&m))

61     {

62         cnt = 0;

63         memset(p,0,sizeof(p));

64         int u,v,w;

65         for(int i = 0; i < m; i++)

66         {

67             scanf("%d %d %d",&u,&v,&w);

68             add(u,v,w);

69         }

70         SPFA(1);

71         printf("%d\n",dis[n]);

72     }

73     return 0;

74 }
View Code

 

 

你可能感兴趣的:(差分约束)