华为软件精英赛总结

津京东北赛区复赛已经结束。

赛题:http://codecraft.huawei.com/home/detail


复赛赛题描述
1 问题定义
给定一个带权重的有向图G=(V,E),V为顶点集,E为有向边集,每一条有向边均有一个权重。对于给定的顶点s、t,以及V的子集V’和V’’,寻找从s到t的两条不成环的有向路径P’和P’’,使得P’经过V’中所有的顶点,而P’’经过V’’中所有的顶点(对P’经过V’中顶点的顺序以及P’’经过V’’中顶点的顺序不做要求)。
若不同时存在这样的两条有向路径,则输出无解,程序运行时间越短,则视为结果越优; 若同时存在这样的两条有向路径,则输出得到的两条路径,按下列优先级从高到低评价结果优劣:
1、 路径P’和P’’重合的有向边个数越少,则视为结果越优;
2、 在两条路径重合的有向边个数一样的情况下,两条路径权重总和越少,则视为结果越优;
3、 在上述两个指标一样的情况下,程序运行时间越短,则视为结果越优。
说明:
1)图中所有权重均为[1,100]内的整数;
2)任一有向边的起点不等于终点;
3)连接顶点A至顶点B的有向边可能超过一条,其权重可能一样,也可能不一样;
4)该有向图的顶点不会超过2000个,每个顶点出度(以该点为起点的有向边的数量)不超过20;
5)V’和V’’中元素个数均不超过100,交集为空,且不包含起始顶点s和终止顶点t;
6)从s到t的不成环有向路径P是指,P为由一系列有向边组成的从s至t的有向连通路径,且不允许重复经过任一顶点;
7)路径的权重是指所有组成该路径的所有有向边的权重之和(重复边的权重应分别在两条路径中各计算一次)。
2 输入与输出
输入文件格式
以两个.csv文件(csv是以逗号为分隔符的文本文件)给出输入数据,一个为图的数据(G),一个为需要计算的路径信息(s,t,V’,V’’)。文件每行以换行符(ASCII’\n’即0x0a)为结尾。

1)图的数据中,每一行包含如下的信息:
LinkID,SourceID,DestinationID,Cost
其中,LinkID为该有向边的索引,SourceID为该有向边的起始顶点的索引,DestinationID为该有向边的终止顶点的索引,Cost为该有向边的权重。顶点与有向边的索引均从0开始编号(不一定连续,但用例保证索引不重复),顶点索引范围在[0,2000),有向边索引范围在[0,40000)。
2)路径信息中,只有一行如下数据:
DemandID,SourceID,DestinationID,IncludingSet
其中,DemandID里面第一行为1,第二行为2,表示路径索引,1表示P’,2表示P’’,SourceID为起始顶点s的索引,DestinationID为终止顶点t的索引,IncludingSet表示必须经过的顶点集合V’或V’’,其中不同的顶点索引之间用“ | ”分割,如果该路径没有必经顶点要求,则此处输入NA。
输出文件格式
输出文件同样为一个.csv 文件。
1)如果该测试用例存在满足要求的有向路径P’和P’’,则输出两行信息,第一行按P’经过的有向边顺序,依次输出有向边的索引,索引之间用“ | ”分割;第二行按P’’经过的有向边顺序依次输出有向边的索引,索引之间用“ | ”分割;
2)如果该测试用例不同时存在两条满足要求的有向路径P’和P’’,则只输出一行信息:NA;
3)每一行只允许输出最多一条有向路径,以换行符0x0a结尾。
3 单个用例的评分机制
有解用例的排名机制
按下面流程对参赛者结果进行排名:
Step1:  对于提交的结果,进行合法性检验(详见题目描述);
Step2:  程序运行时间不得超过10s;
若不满足上述的结果则本用例得分为0;


Step3:  路径P’和P’’重合的有向边个数(不考虑权重)越少,排名越优;
Step4:  在路径P’和P’’重合的有向边个数一样的情况下,计算P’和P’’的权重和,权重越小,排名越优;
Step5:  在上述两个指标一样的情况下,用程序运行时间细化排名,时间越短,排名越优。
无解用例的排名机制
按下列流程对参赛者结果进行排名:
Step1:  对于提交的结果,验证是否识别出该用例无解,若无法识别或者程序运行时间超10s,则本用例得分为0;
Step2:  用程序的运行时间进行排名,时间越短,排名越优。
单个用例的评分标准如下:
根据上面排名流程得到的排名,使用标准分计分(排名第一的提交者为100分)。
若所有人均未得到正确结果,则所有人均得分为0。
4 网站系统判分机制
复赛阶段官方网站开放接收复赛程序提交,系统平台会使用N个测试用例在线判题,参赛者对于每个测试用例都会得到一个百分制分数,使用算术平均分为该参赛者的最终得分,并展示在各区域复赛排行榜中。
特别说明:复赛阶段的在线判题评分及排行仅供参赛者参考,不纳入最终复赛成绩。


首先提提感受:

初赛:本来认为打了这么久acm参加这种比赛是一种实际应用非常兴奋,而且知道这个问题和tsp问题很相似可以找到很多现场的方法。

但是在实际操作中,发现很多方法的效果并不是很好,而且根据数据的规模用不同的方法效果是不一样的

对于其它算法我不清楚具体情况,但是已知的一些方法有:

1.搜索,

2.线性规划

3.遗传

4.蚁群

5.LHK

在初赛的时候,后期线性规划泛滥了,幸好截止时间到了,不然肯定被用求解器的队伍给刷下去,最后29名第一轮进入复赛。可谓惊险啊。

我们队伍使用的是搜索的方法。我和小朱是各自打的,小朱的能跑出前13组case,效果比我的好,我能跑15组case但是接不好。我最高得到95分,但是后来大家根据数据规模做不同的处理,使用不同的算法进行细化以后,各组case的解越来越优,我在不停的下降。最后决定两人合作。前13case小朱跑,我的程序跑最后两组。

我部分的算法思路为:(最后公布代码和用例)

     深度优先搜索,对于一条边,如果该边不能访问剩下的所有必经点,就不走,否则对于当前结点的可行边做评估,然后排序,按顺序访问边。评估的方法有两种,bfs最快访问到必经点,或者最短路最快访问到必经点。复赛的时候增加了预处理,先删除一些肯定不能走的边,判定的方法是:对于点u,如果u的存在一对入边和出边逆向和正向走可以访问所有的必经点则不处理,如果对于一条边e不存在另一条边满足以上情况,则删除e。复赛赛题的做法是用程序对两个必经点各搜索一次找到第一个有效解。剩余的时间每个必经集合的路线求法,随机向前走10步,然后进行搜索。最后对不同必经点得到的解求一个最优匹配。用例的构造方法根据算法对边权不敏感,以及删边的操作,构造了一个有很多无用边,重复边,而且必经路径的边权都很大的数据。

对于该比赛我的思考:

1. 这是一个比时间精力的比赛(当然确实要有一定算法功底),要不断找资料,调试代码,测试结果,优化等等。不是大神只能更努力才能追上前面的队伍。(作为研一的要做项目,上课考试,确实难抽出时间精力)

2.关注新动态,多与他人交流,知道别人在使用什么方法做,有什么资料可以参考,了解各种算法的局限性,如果算法不行就要果断取舍。相互测试比较的过程才知道你的对手有多强,你要做到怎样的效果才能进入下一轮比赛(当然本人没怎么交流,,除了上课的时候会遇到小朱跟他讨论以及跟acm队的几个有兴趣的聊聊,然后在吃饭闲着的时候思考一下,就在周末,完成项目进度的时候写写代码)

3.这一步其实很重要的,就是深刻理解官方的信息,比赛赛制,规则局限性。如:数据是固定不变的,所以可以找出不同数据的特征,然后分算法去求解----这点在复赛被光法禁止了,但是初赛不这么干很容易被刷掉的。官方在出的数据也不太可能压极限,所以知道数据的样子设计对应的算法是不错的选择。复赛时,每对出的题基本自己的代码才会跑出最好的结果,然后你要在官方的数据上跑赢对手,官方的5个case有大小规模的变化,最后两个case基本没有什么队伍跑出来,所以算法在规模难度较小的数据上能出较优结果很重要。同时复赛分组方式,小组赛,淘汰赛的规则要熟知,尽量避免和强的队伍冲突。如:小组赛A1-B2,如果A1超强,那么就别被分到第二组并取得第二的成绩,这在排位赛的时候是可以做一些操作控制一下的。避免分到b组中。

4.关于作弊的事情,林子大了什么鸟都有,好多方法我都不敢想象,攻击服务器,跨区建立假队长,提交他人代码作弊~~~等等的事情我是想不出来,更干不出来。不过得知道这点,才知道自己为什么所处的现在的排名,才不会消极或太乐观。

5. 多打比赛,多去外面看看才知道大神无处不在,北大学力学的两位提着台式机(因为不会在笔记本上装linux)参赛得冠军,我是佩服啊!我非常清楚自己太弱,大神太多,站在任何一处,即使站在了高处都不敢有任何的骄傲了-----因为大神在俯瞰你。---------------------这就是我对于任何人不敢接“大神”称号的原因。但是我并不放弃努力,希望自己真正成为一个大神。保持谦虚,好学不断进步。(这一次外出我认识到一个问题,为什么有人说我喜欢装B,我觉得很无辜和很奇怪,我个人感觉在评价一件事情的时候,都并没有太夸张或者太谦卑的态度,都是站在自己的角度,说出自己真实的感受,不过可能也没考虑别人的感受----好吧,以后得学会做一个中庸的评价)

最后:今昔已败,他日再战,有缘再会!

代码注释,没用到的部分没有删除。见谅。

用例和代码可以到我的资源里下载:

#include "route.h"
#include "lib_record.h"
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <sys/time.h>
#include <time.h>
#include <math.h>
#include <set>
#include <fstream>
#include <bitset>
using namespace std;

namespace GDRetop{
    #define maxV 2001
    #define maxE 40001
    #define maxEdgeCost 200000
    #define maxNeedPointNum 105
    int getSystemTime();
    void stringAnalysis(char *word,vector<int>& result);
    void getBestAnser(vector<vector<int> >&a,vector<vector<int> >&b);
    //=================================================================================
    vector<int> sourceEdge[maxE];
    vector<int> needVertex[2];
    bitset<maxV> occurVertex; //出现过的点
    vector<vector<int> >ansPathOne,ansPathTwo;
    int mark =0,markM[maxV],edgeNum,vertexNum;
    struct Edge{
        int u,v,c,id,dist;
        Edge(){}
        Edge(vector<int> e){
            id = e[0];
            u = e[1];
            v = e[2];
            c = e[3];
        }
        bool operator < (const Edge& b)const{
            return c < b.c;
        }
    };
    struct WholeEdge{
        int u,v;
        int c[2];
        vector<Edge> edge;
        WholeEdge(){}
    };
    vector<WholeEdge> wholeEdge;
    vector<int> nodeEdge[maxV];
    class Search{
        public:
            struct Node{
                int id,v;
                Node(){}
                Node(int _id,int _v):id(_id),v(_v){}
            };
            vector<vector<int> > resultPath;
            bitset<maxE> usefulEdge;          //边是否有效
            bitset<maxV> needPoint;           //是否需要的点
            bitset<maxE> findForward;                 //判断被访问过的边 前向
            bitset<maxNeedPointNum> dpForward[maxE];  //dp 用于判定访问了哪些点,前向
            bitset<maxE> findBack;                    //判断被访问过的边 后向
            bitset<maxNeedPointNum> dpBack[maxE];     //dp 用于判定访问了哪些点,后向
            bitset<maxNeedPointNum> checkNeedPoint;

            vector<Node> forwardEdgeId[maxV]; //前向路径
            vector<Node> backEdgeId[maxV];    //后向路径
            int vertexNumber,que[maxV],mapToId[maxV];
            bitset<maxV> checkVertex;         //临时判定点变量
            bitset<maxE> checkEdge;           //临时判定边变量

            int check[maxV];
            int startTime,endTime,TimeLong;
            int needVnum,covernum,startV,endV,maxCost;
            int queue[maxV],from[maxV];
            int maxDist,type;
            struct searchEdge{
                int u,v,c,id,dist;
                searchEdge(){}
                searchEdge(WholeEdge & we,int _id){
                    u = we.u;
                    v = we.v;
                    id = _id;
                    c = we.c[0];
                }
                bool operator < (const searchEdge& b)const{
                    if(dist == b.dist) return c < b.c;
                    return dist < b.dist;
                }
            };
            vector<searchEdge> edgeTo[maxV];
            vector<int> needVertex;
            vector<int> route;
            int depth[maxV];
            //初始化地图
            void initGraph(vector<int> &need,int timeLimit){
                int initTime = getSystemTime();
                vertexNumber = vertexNum;
                needVertex = need;
                needPoint.reset();
                checkNeedPoint.reset();
                for(int i = 0;i < needVertex.size();i++){
                    needPoint.set(needVertex[i]);
                    checkNeedPoint.set(i);
                }
                needVnum = needVertex.size();
                memset(mapToId,-1,sizeof(mapToId));
                for(int i = 0;i < needVertex.size();i++)
                    mapToId[needVertex[i]] = i;

                usefulEdge.reset();
                for(int i = 0;i < wholeEdge.size();i++){
                    usefulEdge.set(i);
                }
                maxDist = maxEdgeCost;
                startV = needVertex[0];
                endV = needVertex[1];
                initGraph();
                int ans = 0,res = wholeEdge.size();
                vector<int> q;
                int tail = 0;
                checkVertex.reset();
                checkVertex.set(startV);
                q.push_back(startV);
                depth[startV] = 5;
                while(tail < q.size()){
                    int u = q[tail++];
                    for(int i = 0;i < forwardEdgeId[u].size();i++){
                        int v = forwardEdgeId[u][i].v;
                        if(checkVertex.test(v) == false){
                            checkVertex.set(v);
                            q.push_back(v);
                            depth[v] = depth[u]-1;
                        }
                    }
                }

                for(int i = 1;i < q.size();i++){
                    if(occurVertex.test(i) ){
                        edgeCut(q[i]);
                        //initGraph();
                        ans = usefulEdge.count();
//                        if(res - ans > 200){
//                            res = ans;
//                            initGraph();
//                        }
//                        for(int j = 0;j < wholeEdge.size();j++){
//                            if(usefulEdge.test(j)) ans++;
//                        }
                        //cout<<q[i]<<" "<<res - usefulEdge.count()<<endl;
                        res = usefulEdge.count();
                        if(getSystemTime() - initTime > timeLimit) goto aaa ;
                        //if(ans != res) {cout<<"edge less: "<<i<<" "<<res-ans<<" "<<ans<<endl; res =ans;}
                   }
                }
                aaa:
                for(int i = 0;i <= vertexNumber; i++){
                    edgeTo[i].clear();
                }
                for(int i = 0;i < wholeEdge.size();i++){
                    if(usefulEdge.test(i)){
                        int u = wholeEdge[i].u;
                        edgeTo[u].push_back(searchEdge(wholeEdge[i],i));
                    }
                }
            }
            //构建边
            void initGraph(){
                for(int i = 0;i <= vertexNumber; i++){
                    forwardEdgeId[i].clear();
                    backEdgeId[i].clear();
                }
                for(int i = 0;i < wholeEdge.size();i++){
                    if(usefulEdge.test(i)){
                        forwardEdgeId[wholeEdge[i].u].push_back(Node(i,wholeEdge[i].v));
                        backEdgeId[wholeEdge[i].v].push_back(Node(i,wholeEdge[i].u));
                    }
                }
            }
            //割边
            void edgeCut(int u){
                findForward = findBack = usefulEdge;
                static bitset<maxNeedPointNum> begin;
                begin.reset();
                if(needPoint.test(u)){
                    begin.set(mapToId[u]);
                }
                countVisitNeed(startV,u,forwardEdgeId,begin);
                checkEdge = usefulEdge;
                //if(begin == checkNeedPoint) return;
                memset(check,0,sizeof(check));
                tarstack.clear();
                tarMark = 0,newid  = 0;
                for(int i = 0;i < forwardEdgeId[u].size();i++){
                    checkEdge.reset(forwardEdgeId[u][i].id);
                    if(check[forwardEdgeId[u][i].v] == 0 && usefulEdge.test(forwardEdgeId[u][i].id)){
                        tarJan(forwardEdgeId[u][i].v,u,forwardEdgeId);
                    }
                }

                checkVertex.reset();
                for(int i = 0;i < forwardEdgeId[u].size(); i++){
                    if(usefulEdge.test(forwardEdgeId[u][i].id))
                        updateEdgestate(tarbelong[forwardEdgeId[u][i].v],dpForward,forwardEdgeId);
                }
                for(int i = 0;i <= vertexNum ;i++)
                    tarbelongback[i] = tarbelong[i];

                memset(check,0,sizeof(check));
                tarstack.clear();
                tarMark = 0,newid  = 0;
                for(int i = 0;i < backEdgeId[u].size();i++){
                    checkEdge.reset(backEdgeId[u][i].id);
                    if(check[backEdgeId[u][i].v] == 0 && usefulEdge.test(backEdgeId[u][i].id)){
                        tarJan(backEdgeId[u][i].v,u,backEdgeId);
                    }
                }
                checkVertex.reset();
                for(int i = 0;i < backEdgeId[u].size(); i++){
                    if(usefulEdge.test(backEdgeId[u][i].id))
                        updateEdgestate(tarbelong[backEdgeId[u][i].v],dpBack,backEdgeId);
                }

                if(u != startV && begin != checkNeedPoint){
                    usefulEdge ^= checkEdge;
                }
                //return ;
                for(int i = 0;i < forwardEdgeId[u].size(); i++){
                    int flag = 1;
                    if(usefulEdge.test(forwardEdgeId[u][i].id) == false)
                        continue;
                    int ux = tarbelongback[forwardEdgeId[u][i].v];
                    if(needPoint[u])
                        dpForward[ux].set(mapToId[u]);
                    if(dpForward[ux] == checkNeedPoint) continue;
                    for(int j = 0;j < backEdgeId[u].size() && flag; j++){
                        if(usefulEdge.test(backEdgeId[u][j].id) == false)
                            continue;
                        int vx = tarbelong[backEdgeId[u][j].v];
                        if((dpForward[ux] | dpBack[vx]) == checkNeedPoint)
                            flag = 0;
                    }
                    if(flag)
                        usefulEdge.reset(forwardEdgeId[u][i].id);
                }
                for(int i = 1;i < backEdgeId[u].size(); i++){
                    if(usefulEdge.test(backEdgeId[u][i].id) == false)
                        continue;
                    int vx = tarbelong[backEdgeId[u][i].v];
                    if(dpBack[vx] == checkNeedPoint) continue;
                    int flag = 1;
                    for(int j = 0;j < forwardEdgeId[u].size(); j++){
                        if(usefulEdge.test(forwardEdgeId[u][j].id) == false)
                            continue;
                        int ux = tarbelongback[forwardEdgeId[u][j].v];
                        if((dpForward[ux] | dpBack[vx]) == checkNeedPoint)
                            flag = 0;
                    }
                    if(flag)
                        usefulEdge.reset(backEdgeId[u][i].id);
                }
            }
            int tarMark,newid = 0;
            vector<int> contain[maxV],tarstack;
            int tarbelong[maxV],tarbelongback[maxV],tarfloor[maxV],tarCheck[maxV];
            void tarJan(int u,int f,vector<Node>edge[]){
                tarfloor[u] = tarCheck[u] = ++tarMark;
                tarstack.push_back(u);
                check[u] = 1;
                for(int i = 0;i < edge[u].size(); i++){
                    if(usefulEdge[edge[u][i].id] == false) continue;
                    checkEdge.reset(edge[u][i].id);
                    int v = edge[u][i].v;
                    if(v == f) continue;
                    if(check[v] == 1) tarfloor[u] = min(tarfloor[u],tarfloor[v]);
                    else if(check[v] == 0) {
                        tarJan(v,f,edge);
                        tarfloor[u] = min(tarfloor[u],tarfloor[v]);
                    }
                }
                if(tarCheck[u] == tarfloor[u]){
                    contain[newid].clear();
                    int v;
                    do{
                        v = tarstack.back();
                        tarstack.pop_back();
                        tarbelong[v] = newid;
                        contain[newid].push_back(v);
                        check[v] = 2;
                    }while(u != v);
                    newid++;
                }
            }

            void updateEdgestate(int u,bitset<maxNeedPointNum> dp[],vector<Node>edge[]){
                if(checkVertex.test(u)) return;
                checkVertex.set(u);
                dp[u].reset();
                for(int i = 0;i < contain[u].size() ;i++){
                    int v = contain[u][i];
                    if(needPoint.test(v))
                        dp[u].set(mapToId[v]);
                    for(int j = 0;j < edge[v].size(); j++){
                        int id = edge[v][j].id;
                        int vv = edge[v][j].v;
                        if(usefulEdge.test(id) && tarbelong[vv] != u){
                            updateEdgestate(tarbelong[vv],dp,edge);
                            dp[u] |= dp[tarbelong[vv]];
                        }
                    }
                }
            }

            //获取能访问到的点
            void countVisitNeed(int s,int u,vector<Node> edge[],bitset<maxNeedPointNum>& get){
                if(s == u) return ;
                //cout<<s<<" "<<u<<" ";
                checkVertex.reset();
                int top = 0, tail = 0;
                if(needPoint.test(s))
                    get.set(mapToId[s]);
                que[top++] = s;
                checkVertex.set(s);

                while(tail < top){
                    s = que[tail++];
                    for(int i = 0;i < edge[s].size() ;i++){
                        if(edge[s][i].v == u) continue;
                        checkEdge.reset(edge[s][i].id);
                        if(checkVertex.test(edge[s][i].v) == false && usefulEdge.test(edge[s][i].id)){
                            que[top++] = edge[s][i].v;
                            checkVertex.set(edge[s][i].v);
                            if(needPoint.test(edge[s][i].v))
                                get.set(mapToId[edge[s][i].v]);
                        }
                    }
                }
                //cout<<tail<<endl;
            }

            void init(int Time,int tp){
                mark = 1;
                memset(markM,0,sizeof(markM));
                type = tp;
                //resultPath.clear();
                startTime = getSystemTime();
                TimeLong = Time;
                route.clear();
                covernum = needVnum - 1;
                maxCost = 1000000;
                memset(check,0,sizeof(check));
                check[startV] = 1;
                ansSize = 0;
                int EendT = getSystemTime() + TimeLong;
                while(getSystemTime() < EendT){
                    if(resultPath.size() > 100) break;
                    startTime = getSystemTime();
                    TimeLong = 0.5 * CLOCKS_PER_SEC;
                    //cout<<"begin"<<endl;
                    dfs_A(startV,0,10);
                    //cout<<"next "<<" "<<TimeLong<<" "<<getSystemTime() - startTime<<" "<<resultPath.size()<<endl;
                }
            }
            void init0(int Time,int tp){
                mark = 1;
                memset(markM,0,sizeof(markM));
                type = tp;
                //resultPath.clear();
                startTime = getSystemTime();
                TimeLong = Time;
                route.clear();
                covernum = needVnum - 1;
                maxCost = 1000000;
                memset(check,0,sizeof(check));
                check[startV] = 1;
                ansSize = 0;
                dfs_A(startV,0,0);
            }

            struct BEdge{
                int u,dist;
                bool operator < (const BEdge b)const{
                    if(dist == b.dist) return u > b.u;
                    return dist < b.dist;
                }
            };
            int dist[maxV];
            int ansSize;
            void dfs_A(int u,int cost,int lessN){
                if(resultPath.size() > 100) return;
                int flagAns = resultPath.size();
                endTime = getSystemTime();
                int overSize = ansSize;
                if(endTime - startTime > TimeLong ) return ;
               // if(cost >= maxCost ) return ;
                if(u == endV && covernum == 0 ){
                    static int ansnumber = 0;
                    //cout<<"get:"<<type<<"::"<<ansnumber++<<endl;
                    resultPath.push_back(route);
                    maxCost = cost;
                    //cout<<"time:"<<getSystemTime()-startTime<<" new anser "<<maxCost<<endl;
                    return ;
                }
                if(u == endV) return ;
                if(needPoint[u]) ansSize++;
                for(int i = 0 ;i < edgeTo[u].size() ;i++){
                    mark++;
                    edgeTo[u][i].dist = dfs_cut(edgeTo[u][i].v);
                    if(edgeTo[u][i].dist == covernum) edgeTo[u][i].dist = 1;
                    else edgeTo[u][i].dist = -1;
                }

                for(int i = 0;i < edgeTo[u].size() ;i++){
                    if(edgeTo[u][i].dist == 1){
                        mark++;
                        edgeTo[u][i].dist = bfs_find(edgeTo[u][i].v);
                    }
                }
                //cout<<"hehe"<<endl;
                sort(edgeTo[u].begin(),edgeTo[u].end());
                for(int i = 0;i < edgeTo[u].size() ; i++){
                    if(lessN > 0) i = rand() % edgeTo[u].size();
                    if(edgeTo[u][i].dist != -1){
                        int v = edgeTo[u][i].v;
                        check[v] = 1;
                        route.push_back(edgeTo[u][i].id);
                        if(needPoint[v]) covernum--;
                        dfs_A(v,cost+edgeTo[u][i].c,lessN-1);
                        if(needPoint[v]) covernum++;
                        route.pop_back();
                        check[v] = 0;
                    }
                    if(lessN >0) return ;
                    if(flagAns  < resultPath.size()) break;
                }
                //cout<<"haha"<<endl;
            }
            int dfs_cut(int u){
                if(markM[u] == mark || check[u]) return 0;
                int ans = 0;
                markM[u] = mark;
                if(needPoint[u] ) ans++;
                if(u == endV) return ans;
                for(int i = 0;i < edgeTo[u].size(); i++){
                    ans += dfs_cut(edgeTo[u][i].v);
                }
                return ans;
            }
            int bfs_find(int u){
                if(needPoint[u]) return 0;
                if(type == 0){
                memset(dist,0x3f,sizeof(dist));
                set<BEdge> haha;
                BEdge x,y;
                x.u = u;
                x.dist = 0;
                dist[u] = 0;
                haha.insert(x);
                while(haha.size() > 0){
                    x = *haha.begin();
                    haha.erase(haha.begin());
                    if(x.dist > dist[x.u]) continue;
                    for(int i = 0;i < edgeTo[x.u].size(); i++){
                        int v = edgeTo[x.u][i].v;
                        if(check[v]) continue;
                        if(v == endV && covernum != 1) continue;
                        if(needPoint[v]) return x.dist + edgeTo[x.u][i].c;
                        y.u = v;
                        y.dist = x.dist + edgeTo[x.u][i].c;
                        if(y.dist < dist[v]){
                            dist[v] = y.dist;
                            haha.insert(y);
                        }
                    }
                }
                    return -1;
                }


                int top = 1,tail = 0;
                queue[0] = u;
                markM[u] = mark;
                from[u] = 0;
                while(tail < top){
                    u = queue[tail++];
                    for(int i = 0;i < edgeTo[u].size(); i++){
                        int v = edgeTo[u][i].v;
                        if(check[v] || markM[v] == mark) continue;
                        if(v == endV && covernum != 1) continue;
                        if(needPoint[v]) return from[u]+1;
                        queue[top++] = v;
                        from[v] = from[u]+1;
                        markM[v] = mark;
                    }
                }
                return -1;
            }

            void ans_check(vector<int> ansPath){
                if(startV != wholeEdge[ansPath[0]].u) printf("Wrong at begin vertex!\n");
                if(endV != wholeEdge[ansPath[ansPath.size()-1]].v) printf("Wrong at end vertex!\n");
                bitset<maxNeedPointNum> xc;
                xc.reset();
                for(int i = 0;i < ansPath.size(); i++){
                    if(needPoint.test(wholeEdge[ansPath[i]].v))
                        xc.set(mapToId[wholeEdge[ansPath[i]].v]);
                    if(needPoint.test(wholeEdge[ansPath[i]].u))
                        xc.set(mapToId[wholeEdge[ansPath[i]].u]);
                    if(ansPath[i] < 0 || ansPath[i] > edgeNum) printf("Wrong link ID at %d!\n",ansPath[i]);
                    else {
                        if(i > 0){
                            if(wholeEdge[ansPath[i]].u != wholeEdge[ansPath[i-1]].v)
                                printf("The adjacent edge without same vertex at [%d,%d]!\n",wholeEdge[ansPath[i-1]].v,wholeEdge[ansPath[i]].u );
                        }
                    }
                    for(int j = 0;j < i; j++){
                        if(ansPath[i] == ansPath[j])
                            printf("repass link [%d]!\n",ansPath[i]);
                    }
                }
                if(xc != checkNeedPoint) cout<<"wrong anser"<<endl;
                //cout<<"check over"<<endl;
            }
    };

    void init(){
        wholeEdge.clear();
        for(int i = 0;i < maxV ;i++)
            nodeEdge[i].clear();
    }
    void search_route(char *topo[MAX_EDGE_NUM], int edge_num, char *demand[MAX_DEMAND_NUM], int demand_num){
        int beginTime = getSystemTime();
        cout<<"begintime: "<<beginTime<<endl;
         //================================================================================================== Demand
        for(int i = 0;i < demand_num; i++){
            stringAnalysis(demand[i],needVertex[i]);
            needVertex[i].erase(needVertex[i].begin());
            //for(int j = 0;j < needVertex[i].size(); j++)
                //cout<<needVertex[i][j]<<" ";cout<<endl;
        }
        //================================================================================================== Edge
        vector<int> cluster;
        vertexNum = 0;
        set<int> getNode;
        occurVertex.reset();
        edgeNum = edge_num;
        for(int i = 0;i < edge_num; i++){
            stringAnalysis(topo[i],sourceEdge[i]);
            Edge newEdge(sourceEdge[i]);
            int u = newEdge.u,flag = 0;
            getNode.insert(newEdge.u);
            getNode.insert(newEdge.v);
            vertexNum = max(vertexNum,max(newEdge.u,newEdge.v));
            occurVertex.set(newEdge.u);
            occurVertex.set(newEdge.v);
            if(newEdge.u == needVertex[0][1]) continue;
            if(newEdge.v == needVertex[0][0]) continue;
            if(newEdge.u == newEdge.v) continue;
            for(int j = 0;j < nodeEdge[u].size();j++){
                if(wholeEdge[nodeEdge[u][j]].v == newEdge.v){
                    wholeEdge[nodeEdge[u][j]].edge.push_back(newEdge);
                    flag = 1;
                    break;
                }
            }
            if(flag == 0){
                WholeEdge we;
                we.v = newEdge.v;
                we.u = newEdge.u;
                we.edge.push_back(newEdge);
                nodeEdge[newEdge.u].push_back(wholeEdge.size());
                wholeEdge.push_back(we);
            }
        }
        edgeNum = wholeEdge.size();
        for(int i = 0;i < edgeNum ;i++){
            sort(wholeEdge[i].edge.begin(),wholeEdge[i].edge.end());
            wholeEdge[i].c[0] = wholeEdge[i].edge[0].c;
            if(wholeEdge[i].edge.size() > 1)
                wholeEdge[i].c[1] = wholeEdge[i].edge[1].c;
            else
                wholeEdge[i].c[1] = maxEdgeCost;
        }

        //================================================================================================== Information about map
        printf("Total edge: %d   Total vertex: %d \n",edge_num,getNode.size());
        printf("Max vertex number: %d  Left edge number: %d\n",vertexNum,edgeNum);

        Search work1;
        work1.initGraph(needVertex[0],0.5*CLOCKS_PER_SEC);
        //cout<<getSystemTime()-beginTime<<" "<<wholeEdge.size() - work1.usefulEdge.count()<<endl;

        Search work2;
        work2.initGraph(needVertex[1],0.5*CLOCKS_PER_SEC);
        int leftTime = 9*CLOCKS_PER_SEC - getSystemTime() + beginTime;
        work1.init0(leftTime/2,0);
        work2.init0(leftTime/2,1);
        leftTime = 9*CLOCKS_PER_SEC - getSystemTime() + beginTime;
        //cout<<"left Time: "<<leftTime<<endl;
        work1.init(leftTime/2,0);
        work2.init(leftTime/2,1);
        //cout<<work1.resultPath.size()<< " "<<work2.resultPath.size();
        //cout<<"end"<<endl;

        getBestAnser(work1.resultPath,work2.resultPath);
        printf("Total cost time: %d ms\n",getSystemTime()-beginTime);
        return ;
         cout<<"ans check"<<endl;
        for(int i = 0;i < work1.resultPath.size();i++)
            work1.ans_check(work1.resultPath[i]);
        for(int i = 0;i < work2.resultPath.size();i++)
            work2.ans_check(work2.resultPath[i]);
    }

    void getBestAnser(vector<vector<int> >&a,vector<vector<int> >&b){
        int ansA = 0, ansB = 0;
        set<int> result1[a.size()];
        for(int i = 0;i < a.size(); i++){
            for(int j = 0;j < a[i].size(); j++)
                result1[i].insert(a[i][j]);
        }

        int totalCost = maxEdgeCost * 2005, cost[2];
        for(int i = 0;i < a.size(); i++){

            vector<int>& x = a[i];
            int cost1 = 0;
            for(int j = 0;j < x.size(); j++)
                cost1 += wholeEdge[x[j]].c[0];
            for(int j = 0;j < b.size(); j++){
                vector<int>& y = b[j];
                int cost2 = 0;
                for(int k = 0;k < y.size(); k++){
                    if(result1[i].find(y[k]) != result1[i].end()){
                        cost2 += wholeEdge[y[k]].c[1];
                        if(wholeEdge[y[k]].edge.size() == 1)
                            cost2 += wholeEdge[y[k]].c[0];
                    }
                    else
                        cost2 += wholeEdge[y[k]].c[0];
                }
                if(cost2 + cost1 < totalCost){
                    totalCost = cost1 + cost2;
                    cost[0] = cost1;
                    cost[1] = cost2;
                    ansA = i;
                    ansB = j;
                }
            }
        }
        vector<int>& x = a[ansA];
        vector<int>& y = b[ansB];
        for(int i = 0;i < x.size(); i++)
            record_result(WORK_PATH, wholeEdge[x[i]].edge[0].id);
        for(int i = 0;i < y.size(); i++){
            if(result1[ansA].find(y[i]) != result1[ansA].end()){
                if(wholeEdge[y[i]].edge.size() == 1)
                    record_result(BACK_PATH, wholeEdge[y[i]].edge[0].id);
                else
                    record_result(BACK_PATH, wholeEdge[y[i]].edge[1].id);
            }
            else
                record_result(BACK_PATH, wholeEdge[y[i]].edge[0].id);
        }


        printf("Repeat link: %d   Path 1 Cost: %d  Path 2 Cost: %d Total cost: %d\n",totalCost/maxEdgeCost,cost[0],cost[1]%maxEdgeCost ,cost[0]+cost[1]%maxEdgeCost);
    }

    int getSystemTime(){
       return clock();
    }

    void stringAnalysis(char *word,vector<int>& result){
        result.clear();
        int len = strlen(word);
        int u = 0;
        for(int i = 0;i < len; i++){
            if(word[i] == 'N') return ;
            if(word[i] > '9' || word[i] < '0'){
                result.push_back(u);
                u = 0;
                continue;
            }
            u = word[i] - '0' + u * 10;
        }
        if(u != 0)result.push_back(u);
    }
}
void search_route(char *topo[MAX_EDGE_NUM], int edge_num, char *demand[MAX_DEMAND_NUM], int demand_num)
{
    GDRetop::search_route(topo,edge_num,demand,demand_num);
}

















评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GDRetop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值