├── .gitattributes ├── .gitignore ├── README.md ├── 参考文献 ├── Algorithms for server placement in multiple description based media streaming.pdf ├── An Enhanced Genetic Algorithm for Server Placement in Distributed Interactive Applications - urii3.pdf ├── Coordinated Placement and Replacement for Large-Scale Distributed Caches.pdf ├── On the Placement of Web Server Replicas.pdf ├── Optimal Replica Servers Placement for Content Delivery Network s (Invited).pdf ├── P2P流媒体服务器的最优部署方案研究.pdf ├── Placement Algorithm of Web Server Replicas.pdf ├── 内容分发网络中的代理服务器放置算法.pdf ├── 出题人推荐文献合集 │ ├── Caching the P2P Traffic in ISP Network.pdf │ ├── 不确定性物流网络设计的区间规划模型与算法研究_李利华.caj │ ├── 基于模拟退火算法的逆向物流网络设计研究_戴更新.pdf │ └── 基于遗传算法的再制造逆向物流网络随机选址模型_孙浩.pdf ├── 分布式交互应用中服务器放置问题的启发式算法.pdf ├── 分布式交互应用中服务器放置问题的启发式算法_郑晶晶.pdf ├── 分布式缓存系统中一种优化缓存部署的图算法.pdf ├── 基于CDN的服务器放置策略研究.pdf ├── 基于复杂网络的P2P流媒体网络的研究.pdf ├── 基于模拟退火算法的逆向物流网络设计研究_戴更新.pdf ├── 基于模拟退火遗传算法的聚类分析_武兆慧.pdf ├── 求解TSP问题的改进模拟退火遗传算法_王银年.pdf └── 网络中代理服务器最优放置算法.pdf ├── 整数规划 by Lingo └── officialWebCase.lg4 ├── 赛题介绍 ├── ~$官网层次.docx ├── ~$赛题介绍.docx └── 赛题介绍 _ HUAWEI软件精英挑战赛.pdf ├── 退火+ SPFA by C++ ├── build.sh ├── cdn │ ├── CMakeLists.txt │ ├── cdn.cpp │ ├── deploy.cpp │ ├── deploy.h │ ├── io.cpp │ └── lib │ │ ├── lib_io.h │ │ └── lib_time.h └── readme.txt └── 退火+ SPFA by Java ├── .classpath ├── .project ├── .settings ├── org.eclipse.core.resources.prefs └── org.eclipse.jdt.core.prefs ├── bin └── com │ ├── ConUtil.class │ ├── Deploy.class │ ├── Edge.class │ ├── FileUtil.class │ ├── Fire.class │ ├── GraphAlgo.class │ ├── LogUtil$Time.class │ ├── LogUtil.class │ ├── Main.class │ ├── NetworkGraph.class │ ├── Node.class │ ├── Path.class │ ├── Timer.class │ ├── User.class │ └── Users.class └── src └── com ├── ConUtil.java ├── Deploy.java ├── FileUtil.java ├── Fire.java ├── GraphAlgo.java ├── LogUtil.java ├── Main.java ├── NetworkGraph.java └── Timer.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2017华为软件精英挑战赛/2017HuaweiCodeCraft 2 | 3 | 2017华为软件精英挑战赛HUAWEI code craft比赛历程: 4 | http://www.jianshu.com/p/f960050fd8d8 5 | 6 | 我们是上合赛区的【上江湖南西海】队。初赛38名,复活赛8,game over: 7 | 8 | 这次的赛题依旧涉及图论相关的算法。去年是【未来网络:寻路】,今年是【大视频时代:布局】。连续两年都是图论了,建议明年准备参加比赛的同学可以先把图论给温习了。 9 | 10 | 细分的话,这是一个CDN问题,或者叫做server placement/ facility location问题,总之搜这几个关键词可以拿到很多有价值的论文。建议明年准备参加比赛的同学,拿到赛题后先把问题模型搞清楚,确定其在学术界的名称,然后就可以去搜论文了。看论文是一个非常重要的集思广益的过程。 11 | 12 | 简要地给出我们的timeline: 13 | 14 | 1.一开始打算借鉴去年的线性规划。 15 | 16 | 比赛前期遇到期末考试,断断续续用了一周在Lingo把官网case跑出来了,得到最优解783,但是耗时4s,时间太长了。又尝试自己写单纯形法来解整数规划,逐渐认定手写至少很难和商业上成熟的软件相比,耗时问题难以解决,遂放弃。后来网上有人分享,他用整数规划成功解决大case,用时超过2小时,而解决QQ群里面非官方的终极case则需要耗时一天以上,这条路的确行不通。 17 | 18 | 19 | 2.大事化小,先解决CDN位置确定时的最小费用最大流问题。 20 | 21 | 谢师兄成功写出了SPFA算法,这个是我们比赛过程中的一个关键点。接着我加入超级源点和超级汇点的思想:超级源点连接设定好的CDN(为了方便,接下来服务器都会被简称为CDN),超级汇点连接所有的消费节点所连接的网络节点,并且保证所有消费节点连接到超级汇点的链路带宽即为其带宽需求。至此,当确定某几个节点为CDN时,可以求出最大流为且只能为固定值时的最小费用问题。现在我们只需要想方法来确定CDN位置。 22 | 23 | 24 | 25 | 3.用遗传来确定CDN位置。 26 | 27 | 当时摆在我们面前的主要有退火、遗传这两种启发式搜索方案,我们选择了遗传算法。现在回想起来,这个选择注定是一条更难的路:首先在选择初始种群时走了弯路,尝试了很多种方法来筛选出"CDN候选点",也就是筛选出哪些点可以作为基因,想来减少后期的计算量;其次种群的迭代太慢了,迭代出来的也不一定是可行解;并且遗传有个关键:要保证产生的子代很大几率上是优于父代,才能保证整个过程是在优胜劣汰。这个关键点我们没有处理好,进一步减慢了迭代速度。 28 | 29 | 30 | 4.改用退火算法 31 | 32 | 后来写出了一版退火算法,立马就上64强了,在50-60名之间。退火更加适合于这道题,我认为关键原因在于:退火的求领域解的机制加大了产生可行解的几率,使得迭代的有效率大幅提升。遗传不是不好,而是比起退火来难很多,导致我们一直没有调试出满意结果,当然也可能是我们写残了。一打听周围的参赛同学,才发现那些早就顺利上榜的人用的都是退火算法。 33 | 回过头来,我反思为什么我们在遗传上浪费了太多时间: 不舍得丢弃已有成果,觉得不断努力肯定会有好结果。实际上,应当具备一定的预见能力,觉得行不通尽早换方向。锲而不舍,及时止损,这两者的关系要好好把握与权衡,这可能就是大佬经验比我丰富的地方吧。当然止损也有一条捷径,那就是要在比赛中保持信息畅通,不能闭门造车。如果我们早知道大多数人用的都是退火,自然而然就会更早的转换方向,毕竟重新写一版代码代价太大,没有大把握的话很难有动力去做。所以建议比赛的同学们应当多结识赛友,没人愿意白给你指导,你也得拿有份量的信息去交换,这样得来的信息比在QQ群和博客得来的有用得多。 34 | 35 | 36 | 5.对图预处理、优化与重构。 37 | 38 | 既然已经上榜,那么艰难的爬榜之路就开始了。代码重构主要是师兄在做,每次优化一点儿,名次都能往上爬几名,但是几小时后又会有人爬到我们前面来。大家都在优化,不进则退放这里是再合适不过了。我在做预处理的程序,筛选出必定为CDN的点。这个规律很好找,大case能筛选出30-50个点,大大减少了运算量,名词进入40-50区间。 39 | 40 | 41 | 6.发现重大规律:只需要在消费点直连的网络节点中筛选即可。 42 | 43 | 我们之前一直是在所有点中进行CDN选点。直到有一天,看到了有一个同学分享的用线性规划得到的最优解运算结果。我对他的数据统计分析了一下,发现最优解的CDN位置基本均为消费点直连的网络节点,偶尔有一两个落单的点为普通的网络节点。为了效率,我觉得暂时可以直接在消费点直连的网络节点中进行CDN选点即可。因为这个规律的发现,再加上对图预处理的过程,名次进入了30-40区间。所以无论通过什么方法求解,也许是暴力大法,也许是线性规划,虽然这些方法不可以用在最终代码中,但是可以获得用于参考的最优解。这就相当于做习题时拿到了没有运算过程的最终答案,从答案往过程推导也是一个获得思路的好方法。 44 | 45 | 46 | 7.用C++重写。。。 47 | 48 | 目前为止TOP64至少是保住了,绿卡问题不大了。接下来都在优化与重构,发现Java效率实在底下,迭代次数比C++慢了五倍不止。官方说法是Java和C++差异可以忽略,这个只能参考,千万别采纳。C++作为竞赛语言是有原因的,道理我们都懂,依旧比不好比赛。最终初赛截止时,三个case得分如下: 49 | 复活赛竞争异常激烈,复活赛最终的前四放初赛是可以进前15的(此数据仅供参考,并不严谨)。所以能在初赛完成的目标,千万不要拖到复活赛。用CPP重写后,初级和中级接近满分了,高级case实在没时间调试了,若放初赛这结果进前32是稳的。不过没什么可遗憾的,大佬们的确很厉害,希望自己多汲取教训,多掌握经验。 50 | 51 | 52 | 最终我们的代码构成为:退火算法寻址 + SPFA算法求路径 by C++语言。 53 | 54 | 数十个赛区,只有西北川渝等赛区的竞争才算是白热化,尤其是成电、西电等高校长期30多个队伍霸屏TOP64榜,而其他赛区进TOP64和拿绿卡难度并不大。所以我明年肯定会推荐学弟学妹们来参加这个比赛,性价比还是很高的。 55 | 56 | 比赛过程中,偶遇开发者论坛愚人节活动。运气比较好,我们队三个人拿了两套华为code craft卫衣和小原公仔。感谢我的队友:谢师兄和任同学,尤其感谢他们给我做队长的机会,比赛完带队友们去赤坂亭吃了一顿饭,放张照弱弱地纪念一下: 57 | 58 | 写下这篇文章,主要是给自己队伍的工作做个总结,也给其他和我一样的"小白"提供参赛经验。欢迎关注,欢迎讨论。 59 | -------------------------------------------------------------------------------- /参考文献/Algorithms for server placement in multiple description based media streaming.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/Algorithms for server placement in multiple description based media streaming.pdf -------------------------------------------------------------------------------- /参考文献/An Enhanced Genetic Algorithm for Server Placement in Distributed Interactive Applications - urii3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/An Enhanced Genetic Algorithm for Server Placement in Distributed Interactive Applications - urii3.pdf -------------------------------------------------------------------------------- /参考文献/Coordinated Placement and Replacement for Large-Scale Distributed Caches.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/Coordinated Placement and Replacement for Large-Scale Distributed Caches.pdf -------------------------------------------------------------------------------- /参考文献/On the Placement of Web Server Replicas.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/On the Placement of Web Server Replicas.pdf -------------------------------------------------------------------------------- /参考文献/Optimal Replica Servers Placement for Content Delivery Network s (Invited).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/Optimal Replica Servers Placement for Content Delivery Network s (Invited).pdf -------------------------------------------------------------------------------- /参考文献/P2P流媒体服务器的最优部署方案研究.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/P2P流媒体服务器的最优部署方案研究.pdf -------------------------------------------------------------------------------- /参考文献/Placement Algorithm of Web Server Replicas.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/Placement Algorithm of Web Server Replicas.pdf -------------------------------------------------------------------------------- /参考文献/内容分发网络中的代理服务器放置算法.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/内容分发网络中的代理服务器放置算法.pdf -------------------------------------------------------------------------------- /参考文献/出题人推荐文献合集/Caching the P2P Traffic in ISP Network.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/出题人推荐文献合集/Caching the P2P Traffic in ISP Network.pdf -------------------------------------------------------------------------------- /参考文献/出题人推荐文献合集/不确定性物流网络设计的区间规划模型与算法研究_李利华.caj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/出题人推荐文献合集/不确定性物流网络设计的区间规划模型与算法研究_李利华.caj -------------------------------------------------------------------------------- /参考文献/出题人推荐文献合集/基于模拟退火算法的逆向物流网络设计研究_戴更新.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/出题人推荐文献合集/基于模拟退火算法的逆向物流网络设计研究_戴更新.pdf -------------------------------------------------------------------------------- /参考文献/出题人推荐文献合集/基于遗传算法的再制造逆向物流网络随机选址模型_孙浩.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/出题人推荐文献合集/基于遗传算法的再制造逆向物流网络随机选址模型_孙浩.pdf -------------------------------------------------------------------------------- /参考文献/分布式交互应用中服务器放置问题的启发式算法.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/分布式交互应用中服务器放置问题的启发式算法.pdf -------------------------------------------------------------------------------- /参考文献/分布式交互应用中服务器放置问题的启发式算法_郑晶晶.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/分布式交互应用中服务器放置问题的启发式算法_郑晶晶.pdf -------------------------------------------------------------------------------- /参考文献/分布式缓存系统中一种优化缓存部署的图算法.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/分布式缓存系统中一种优化缓存部署的图算法.pdf -------------------------------------------------------------------------------- /参考文献/基于CDN的服务器放置策略研究.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/基于CDN的服务器放置策略研究.pdf -------------------------------------------------------------------------------- /参考文献/基于复杂网络的P2P流媒体网络的研究.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/基于复杂网络的P2P流媒体网络的研究.pdf -------------------------------------------------------------------------------- /参考文献/基于模拟退火算法的逆向物流网络设计研究_戴更新.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/基于模拟退火算法的逆向物流网络设计研究_戴更新.pdf -------------------------------------------------------------------------------- /参考文献/基于模拟退火遗传算法的聚类分析_武兆慧.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/基于模拟退火遗传算法的聚类分析_武兆慧.pdf -------------------------------------------------------------------------------- /参考文献/求解TSP问题的改进模拟退火遗传算法_王银年.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/求解TSP问题的改进模拟退火遗传算法_王银年.pdf -------------------------------------------------------------------------------- /参考文献/网络中代理服务器最优放置算法.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/参考文献/网络中代理服务器最优放置算法.pdf -------------------------------------------------------------------------------- /整数规划 by Lingo/officialWebCase.lg4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/整数规划 by Lingo/officialWebCase.lg4 -------------------------------------------------------------------------------- /赛题介绍/~$官网层次.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/赛题介绍/~$官网层次.docx -------------------------------------------------------------------------------- /赛题介绍/~$赛题介绍.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/赛题介绍/~$赛题介绍.docx -------------------------------------------------------------------------------- /赛题介绍/赛题介绍 _ HUAWEI软件精英挑战赛.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/赛题介绍/赛题介绍 _ HUAWEI软件精英挑战赛.pdf -------------------------------------------------------------------------------- /退火+ SPFA by C++/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT=$(readlink -f "$0") 4 | BASEDIR=$(dirname "$SCRIPT") 5 | cd $BASEDIR 6 | 7 | if [ ! -d cdn ] || [ ! -f readme.txt ] 8 | then 9 | echo "ERROR: $BASEDIR is not a valid directory of SDK-gcc for cdn." 10 | echo " Please run this script in a regular directory of SDK-gcc." 11 | exit -1 12 | fi 13 | 14 | tmp=$(cmake --version 2>&1) 15 | if [ $? -ne 0 ] 16 | then 17 | echo "ERROR: You should install cmake(2.8 or later) first." 18 | echo " Please run 'sudo apt-get install cmake' to install it." 19 | echo " or goto https://cmake.org to download and install it." 20 | exit 21 | fi 22 | 23 | rm -fr bin 24 | mkdir bin 25 | rm -fr build 26 | mkdir build 27 | cd build 28 | cmake ../cdn 29 | make 30 | 31 | cd .. 32 | tar -zcPf cdn.tar.gz * 33 | -------------------------------------------------------------------------------- /退火+ SPFA by C++/cdn/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake 最低版本号要求 2 | cmake_minimum_required(VERSION 2.8) 3 | 4 | # 项目信息 5 | project(cdn) 6 | 7 | # include路径 8 | include_directories(${PROJECT_SOURCE_DIR}/lib) 9 | 10 | # 设置可执行文件生成路径 11 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin) 12 | 13 | # 生成debug版本 14 | SET(CMAKE_BUILD_TYPE "release") 15 | if (CMAKE_BUILD_TYPE STREQUAL debug) 16 | add_definitions(-D_DEBUG) 17 | endif () 18 | SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb -std=c++11") 19 | SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall -std=c++11") 20 | 21 | # 查找当前目录下的所有源文件 22 | # 并将名称保存到 DIR_LIB_SRCS 变量 23 | aux_source_directory(. DIR_SRCS) 24 | 25 | # 指定生成目标 26 | add_executable(cdn ${DIR_SRCS}) 27 | -------------------------------------------------------------------------------- /退火+ SPFA by C++/cdn/cdn.cpp: -------------------------------------------------------------------------------- 1 | #include "deploy.h" 2 | #include "lib_io.h" 3 | #include "lib_time.h" 4 | #include "stdio.h" 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | print_time("Begin"); 9 | char *topo[MAX_EDGE_NUM]; 10 | int line_num; 11 | 12 | char *topo_file = argv[1]; 13 | 14 | line_num = read_file(topo, MAX_EDGE_NUM, topo_file); 15 | 16 | printf("line num is :%d \n", line_num); 17 | if (line_num == 0) 18 | { 19 | printf("Please input valid topo file.\n"); 20 | return -1; 21 | } 22 | 23 | char *result_file = argv[2]; 24 | 25 | deploy_server(topo, line_num, result_file); 26 | 27 | release_buff(topo, line_num); 28 | 29 | print_time("End"); 30 | 31 | return 0; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /退火+ SPFA by C++/cdn/deploy.cpp: -------------------------------------------------------------------------------- 1 | #include "deploy.h" 2 | #include 3 | 4 | int nodeNum, edgeNum, userNum; 5 | vector nodes[MAX_NODE_NUM]; 6 | bool realCDN[MAX_NODE_NUM]; 7 | 8 | vector edges; 9 | int cdnCost; 10 | int totalReq; 11 | 12 | int superSourceId; 13 | int superSinkId; 14 | 15 | int map_NdToUser[MAX_NODE_NUM]; 16 | int map_UserToNd[MAX_USER_NUM]; 17 | int user_req[MAX_USER_NUM]; 18 | int MAX_Int = numeric_limits::max(); 19 | 20 | int bestCost; 21 | vector bestPaths; 22 | 23 | //SPFA相关变量 24 | int aug[MAX_NODE_NUM]; 25 | int disTo[MAX_NODE_NUM]; 26 | int edgeTo[MAX_NODE_NUM]; 27 | int inQ[MAX_NODE_NUM]; 28 | 29 | char * result_file; 30 | string topo_file; 31 | 32 | //SA参量 33 | double curT; 34 | double deCold; 35 | int interTimes; 36 | int outerTimes; 37 | double p; 38 | vector newCDNNdIds; 39 | vector neighbors[MAX_NODE_NUM]; 40 | vector userNeighbors[MAX_NODE_NUM]; 41 | 42 | bool run = true; 43 | 44 | //你要完成的功能总入口 45 | void deploy_server(char * topo[MAX_EDGE_NUM], int line_num, char * filename) 46 | { 47 | signal(SIGALRM, handler); 48 | result_file = filename; 49 | topo_file = ""; 50 | //初始化 51 | nodeNum = 0; 52 | edgeNum = 0; 53 | userNum = 0; 54 | cdnCost = 0; 55 | totalReq = 0; 56 | superSourceId = 0; 57 | superSinkId = 0; 58 | bestCost = MAX_Int; 59 | 60 | for(int i = 0; i < MAX_NODE_NUM; i++) 61 | { 62 | nodes[i].clear(); 63 | neighbors[i].clear(); 64 | userNeighbors[i].clear(); 65 | } 66 | 67 | edges.clear(); 68 | bestPaths.clear(); 69 | newCDNNdIds.clear(); 70 | 71 | memset(map_NdToUser, -1, sizeof(map_NdToUser)); 72 | memset(map_UserToNd, -1, sizeof(map_UserToNd)); 73 | memset(user_req, 0, sizeof(user_req)); 74 | memset(realCDN, 0, sizeof(realCDN)); 75 | 76 | memset(aug, 0, sizeof(aug)); 77 | memset(disTo, MAX_Int, sizeof(disTo)); 78 | memset(edgeTo, -1, sizeof(edgeTo)); 79 | memset(inQ, 0, sizeof(inQ)); 80 | 81 | //读取基本数据 82 | char *charIndex = NULL; 83 | charIndex = charToNum(topo[0], nodeNum); 84 | charIndex = charToNum(charIndex, edgeNum); 85 | charIndex = charToNum(charIndex, userNum); 86 | charIndex = charToNum(topo[2], cdnCost); 87 | 88 | // printf("%d ", nodeNum); 89 | // printf("%d ", edgeNum); 90 | // printf("%d ", userNum); 91 | // printf("%d\n", cdnCost); 92 | 93 | //设置超级原点 94 | superSourceId = nodeNum; 95 | //设置超级聚点 96 | superSinkId = nodeNum + 1; 97 | 98 | 99 | //记录边信息 100 | int countEdges = 4 + edgeNum; 101 | for(int i = 4; i < countEdges; i++) 102 | { 103 | int Nd1; 104 | int Nd2; 105 | int capacity; 106 | int cost; 107 | 108 | charIndex = charToNum(topo[i], Nd1); 109 | charIndex = charToNum(charIndex, Nd2); 110 | charIndex = charToNum(charIndex, capacity); 111 | charIndex = charToNum(charIndex, cost); 112 | 113 | // printf("%d ", Nd1); 114 | // printf("%d ", Nd2); 115 | // printf("%d ", capacity); 116 | // printf("%d\n", cost); 117 | 118 | edges.push_back(Edge(Nd1, Nd2, capacity, cost, 0)); 119 | edges.push_back(Edge(Nd2, Nd1, 0, -cost, 0)); 120 | int m = edges.size(); 121 | nodes[Nd1].push_back(m - 2); 122 | nodes[Nd2].push_back(m - 1); 123 | 124 | edges.push_back(Edge(Nd2, Nd1, capacity, cost, 0)); 125 | edges.push_back(Edge(Nd1, Nd2, 0, -cost, 0)); 126 | m = edges.size(); 127 | nodes[Nd2].push_back(m - 2); 128 | nodes[Nd1].push_back(m - 1); 129 | } 130 | 131 | // printf("\n"); 132 | // printf("%d\n", edges.size()); 133 | // printf("\n"); 134 | 135 | //记录用户信息 136 | int countUsers = countEdges + 1 + userNum; 137 | for(int i = countEdges + 1; i < countUsers; i++) 138 | { 139 | int userId; 140 | int linkedNd; 141 | int req; 142 | 143 | charIndex = charToNum(topo[i], userId); 144 | charIndex = charToNum(charIndex, linkedNd); 145 | charIndex = charToNum(charIndex, req); 146 | 147 | // printf("%d ", userId); 148 | // printf("%d ", linkedNd); 149 | // printf("%d\n", req); 150 | 151 | map_UserToNd[userId] = linkedNd; 152 | map_NdToUser[linkedNd] = userId; 153 | user_req[userId] = req; 154 | totalReq += req; 155 | } 156 | 157 | setAllNeighbors(); 158 | 159 | if(nodeNum < 200) 160 | { 161 | alarm(2); 162 | int toleranceForCandidates = 600; 163 | int toleranceForFixed = 0; 164 | vector cdnNdIds; 165 | addSuperSinkEdges(); 166 | //printf("加边没问题\n"); 167 | while(true) 168 | { 169 | 170 | selfishness(cdnNdIds, toleranceForCandidates); 171 | printf("固定点没问题\n"); 172 | int tmpCost = MinCostMaxFlowSA(cdnNdIds); 173 | if(tmpCost < 0) 174 | { 175 | printf("初始解不可行!!!!!\n"); 176 | toleranceForCandidates += 50; 177 | continue; 178 | } 179 | else 180 | { 181 | printf("初始解可行,开始退火!!!!!\n"); 182 | break; 183 | } 184 | } 185 | vector fixedCdnIds; 186 | selfishness(fixedCdnIds, toleranceForFixed); 187 | printf("fixedCdnIds: %d 个\n", fixedCdnIds.size()); 188 | printf("cdnNdIds: %d 个\n", cdnNdIds.size()); 189 | Fire(2, 1, 5000, 10000, 0.00001); 190 | fireAlgo(cdnNdIds, fixedCdnIds, 1, 0, 1, 0.75); 191 | } 192 | else if(nodeNum < 400) 193 | { 194 | alarm(88); 195 | int toleranceForCandidates = 600; 196 | int toleranceForFixed = 0; 197 | vector cdnNdIds; 198 | addSuperSinkEdges(); 199 | while(true) 200 | { 201 | selfishness(cdnNdIds, toleranceForCandidates); 202 | int tmpCost = MinCostMaxFlowSA(cdnNdIds); 203 | if(tmpCost < 0) 204 | { 205 | printf("初始解不可行!!!!!\n"); 206 | toleranceForCandidates += 50; 207 | continue; 208 | } 209 | else 210 | { 211 | printf("初始解可行,开始退火!!!!!\n"); 212 | break; 213 | } 214 | } 215 | vector fixedCdnIds; 216 | selfishness(fixedCdnIds, toleranceForFixed); 217 | printf("fixedCdnIds: %d 个\n", fixedCdnIds.size()); 218 | printf("cdnNdIds: %d 个\n", cdnNdIds.size()); 219 | Fire(5, 1, 5000, 10000, 0.1); 220 | fireAlgo(cdnNdIds, fixedCdnIds, 1, 1, 1, 0.75); 221 | } 222 | else 223 | { 224 | alarm(88); 225 | int toleranceForCandidates = 800; 226 | int toleranceForFixed = 600; 227 | vector cdnNdIds; 228 | addSuperSinkEdges(); 229 | while(true) 230 | { 231 | selfishness(cdnNdIds, toleranceForCandidates); 232 | int tmpCost = MinCostMaxFlowSA(cdnNdIds); 233 | if(tmpCost < 0) 234 | { 235 | printf("初始解不可行!!!!!\n"); 236 | toleranceForCandidates += 50; 237 | continue; 238 | } 239 | else 240 | { 241 | printf("初始解可行,开始退火!!!!!\n"); 242 | break; 243 | } 244 | } 245 | vector fixedCdnIds; 246 | selfishness(fixedCdnIds, toleranceForFixed); 247 | printf("fixedCdnIds: %d 个\n", fixedCdnIds.size()); 248 | printf("cdnNdIds: %d 个\n", cdnNdIds.size()); 249 | Fire(10, 1, 5000, 10000, 0.1); 250 | fireAlgo(cdnNdIds, fixedCdnIds, 8, 2, 1, 0.99); 251 | } 252 | 253 | printf("bestCost: %d\n", bestCost); 254 | printf("bestPathsSize: %d\n", bestPaths.size()); 255 | 256 | 257 | 258 | // addSuperSinkEdges(); 259 | // vector fixedCdnIds; 260 | // selfishness(fixedCdnIds); 261 | // vector a; 262 | // a.push_back(0); 263 | // a.push_back(3); 264 | // a.push_back(22); 265 | // int cost = MinCostMaxFlowGA(a); 266 | // printf("\n"); 267 | // printf("%d\n", cost); 268 | // printf("\n"); 269 | // 需要输出的内容 270 | //char * topo_file = (char *)"17\n\n0 8 0 20\n21 8 0 20\n9 11 1 13\n21 22 2 20\n23 22 2 8\n1 3 3 11\n24 3 3 17\n27 3 3 26\n24 3 3 10\n18 17 4 11\n1 19 5 26\n1 16 6 15\n15 13 7 13\n4 5 8 18\n2 25 9 15\n0 7 10 10\n23 24 11 23"; 271 | //char * topox = buildTopoResult(); 272 | //string topox; 273 | buildTopoResult(topo_file); 274 | // 直接调用输出文件的方法输出到指定文件中(ps请注意格式的正确性,如果有解,第一行只有一个数据;第二行为空;第三行开始才是具体的数据,数据之间用一个空格分隔开) 275 | write_result((char *)topo_file.data(), result_file); 276 | } 277 | 278 | void Fire(double cT, double dC, int inter, int outer, double ratio) 279 | { 280 | curT = cT; 281 | deCold = dC; 282 | interTimes = inter; 283 | outerTimes = outer; 284 | p = ratio; 285 | } 286 | 287 | void fireAlgo(vector& cdnNdIds, vector& fixedCdnIds, int countForLess, int caseKind, int countForMore, double lessOrMore) 288 | { 289 | int countForLessTMP = countForLess; 290 | double lessOrMoreTMP = lessOrMore; 291 | 292 | vector lastCdnNdIds; 293 | lastCdnNdIds.reserve(cdnNdIds.size()); 294 | lastCdnNdIds.insert(lastCdnNdIds.end(), cdnNdIds.begin(), cdnNdIds.end()); 295 | int lastCost = bestCost; 296 | 297 | vector curCdnNdIds; 298 | int curCost; 299 | 300 | double ran; 301 | double metropolis; 302 | 303 | int countTimes = 0; 304 | //根据规模(caseKind)初始化! 305 | int threshold; 306 | 307 | if(caseKind == 2) 308 | { 309 | threshold = 155; 310 | } 311 | else if(caseKind == 1) 312 | { 313 | threshold = 60; 314 | } 315 | else if(caseKind == 0) 316 | { 317 | threshold = 40; 318 | } 319 | 320 | for(int curOuter = 0; curOuter < outerTimes; curOuter++) 321 | { 322 | for(int curInter = 0; curInter < interTimes; curInter++) 323 | { 324 | while(true) 325 | { 326 | if(!run) return; 327 | if(lastCdnNdIds.size() < threshold) 328 | { 329 | countForLessTMP = 1; 330 | ran = rand() / double(RAND_MAX); 331 | double lowToMid = 0.6; 332 | double midToHigh = 0.8; 333 | if(caseKind == 2) 334 | { 335 | lowToMid = 0.4; 336 | midToHigh = 0.7; 337 | } 338 | while(ran == 1) 339 | { 340 | ran = rand() / double(RAND_MAX); 341 | } 342 | if(ran < lowToMid) 343 | { 344 | curCdnNdIds.clear(); 345 | nearSolusionLESS(lastCdnNdIds, fixedCdnIds, countForLessTMP, caseKind); 346 | curCdnNdIds.reserve(newCDNNdIds.size()); 347 | curCdnNdIds.insert(curCdnNdIds.end(), newCDNNdIds.begin(), newCDNNdIds.end()); 348 | } 349 | else if(ran < midToHigh) 350 | { 351 | curCdnNdIds.clear(); 352 | nearSolusionMORE(lastCdnNdIds, fixedCdnIds, countForMore); 353 | curCdnNdIds.reserve(newCDNNdIds.size()); 354 | curCdnNdIds.insert(curCdnNdIds.end(), newCDNNdIds.begin(), newCDNNdIds.end()); 355 | } 356 | else 357 | { 358 | curCdnNdIds.clear(); 359 | nearSolusionKEEP(lastCdnNdIds, fixedCdnIds, 1); 360 | curCdnNdIds.reserve(newCDNNdIds.size()); 361 | curCdnNdIds.insert(curCdnNdIds.end(), newCDNNdIds.begin(), newCDNNdIds.end()); 362 | } 363 | 364 | } 365 | else 366 | { 367 | ran = rand() / double(RAND_MAX); 368 | while(ran == 1) 369 | { 370 | ran = rand() / double(RAND_MAX); 371 | } 372 | if(ran > lessOrMoreTMP) 373 | { 374 | curCdnNdIds.clear(); 375 | nearSolusionMORE(lastCdnNdIds, fixedCdnIds, countForMore); 376 | curCdnNdIds.reserve(newCDNNdIds.size()); 377 | curCdnNdIds.insert(curCdnNdIds.end(), newCDNNdIds.begin(), newCDNNdIds.end()); 378 | } 379 | else 380 | { 381 | curCdnNdIds.clear(); 382 | nearSolusionLESS(lastCdnNdIds, fixedCdnIds, countForLess, caseKind); 383 | curCdnNdIds.reserve(newCDNNdIds.size()); 384 | curCdnNdIds.insert(curCdnNdIds.end(), newCDNNdIds.begin(), newCDNNdIds.end()); 385 | } 386 | } 387 | countTimes++; 388 | printf("********this is %d diedai********\n", countTimes); 389 | curCost = MinCostMaxFlowSA(curCdnNdIds); 390 | if(curCost == -1) 391 | { 392 | printf("Not available! Continue.\n"); 393 | continue; 394 | } 395 | if(curCost < lastCost) 396 | { 397 | printf("---------------------------------------------\n"); 398 | printf("curCost < lastCost: %d < %d\n", curCost, lastCost); 399 | lastCost = curCost; 400 | lastCdnNdIds.clear(); 401 | lastCdnNdIds.reserve(curCdnNdIds.size()); 402 | lastCdnNdIds.insert(lastCdnNdIds.end(), curCdnNdIds.begin(), curCdnNdIds.end()); 403 | printf("better!!!!! received !!!!! curCost: %d\n", lastCost); 404 | printf("curCDNNum is %d\n", lastCdnNdIds.size()); 405 | printf("---------------------------------------------\n"); 406 | break; 407 | } 408 | metropolis = exp(-(double)(curCost - lastCost)/curT); 409 | printf("---------------------------------------------\n"); 410 | printf("(double) (curCost - lastCost) : %d\n", (curCost - lastCost)); 411 | printf("metropolis : %10f\n", metropolis); 412 | if(metropolis >= p) 413 | { 414 | lastCost = curCost; 415 | lastCdnNdIds.clear(); 416 | lastCdnNdIds.reserve(curCdnNdIds.size()); 417 | lastCdnNdIds.insert(lastCdnNdIds.end(), curCdnNdIds.begin(), curCdnNdIds.end()); 418 | printf("worst a little \n"); 419 | printf("lastCost: %d\n", lastCost); 420 | printf("curCDNNum is %d\n", lastCdnNdIds.size()); 421 | printf("---------------------------------------------\n"); 422 | break; 423 | } 424 | printf("too worst!!! \n"); 425 | printf("lastCost: %d\n", lastCost); 426 | printf("curCDNNum is %d\n", lastCdnNdIds.size()); 427 | printf("---------------------------------------------\n"); 428 | break; 429 | } 430 | } 431 | curT *= deCold; 432 | } 433 | } 434 | 435 | void nearSolusionLESS(vector& lastCdnNdIds, vector& fixedCdnIds, int countForLess, int caseKind) 436 | { 437 | newCDNNdIds.clear(); 438 | newCDNNdIds.reserve(lastCdnNdIds.size()); 439 | newCDNNdIds.insert(newCDNNdIds.end(), lastCdnNdIds.begin(), lastCdnNdIds.end()); 440 | int ran, ranSelectedCdnId; 441 | double ranTMP; 442 | for(int i = 0; i < countForLess; i++) 443 | { 444 | while(true) 445 | { 446 | //printf("-------1--------\n"); 447 | ranTMP = rand() / double(RAND_MAX); 448 | while(ranTMP == 1) 449 | { 450 | //printf("-------2--------\n"); 451 | ranTMP = rand() / double(RAND_MAX); 452 | } 453 | ran = (int)(ranTMP * newCDNNdIds.size()); 454 | ranSelectedCdnId = newCDNNdIds[ran]; 455 | if(!realCDN[ranSelectedCdnId]) 456 | { 457 | break; 458 | } 459 | } 460 | newCDNNdIds.erase(ran + newCDNNdIds.begin()); 461 | } 462 | } 463 | void nearSolusionKEEP(vector& lastCdnNdIds, vector& fixedCdnIds, int countForKeep) 464 | { 465 | newCDNNdIds.clear(); 466 | newCDNNdIds.reserve(lastCdnNdIds.size()); 467 | newCDNNdIds.insert(newCDNNdIds.end(), lastCdnNdIds.begin(), lastCdnNdIds.end()); 468 | int ran, ranSelectedCdnId; 469 | double ranTMP; 470 | for(int i = 0; i < countForKeep; i++) 471 | { 472 | while(true) 473 | { 474 | ranTMP = rand() / double(RAND_MAX); 475 | while(ranTMP == 1) 476 | { 477 | ranTMP = rand() / double(RAND_MAX); 478 | } 479 | ran = (int)(ranTMP * newCDNNdIds.size()); 480 | ranSelectedCdnId = newCDNNdIds[ran]; 481 | if(realCDN[ranSelectedCdnId]) 482 | { 483 | continue; 484 | } 485 | if(userNeighbors[ranSelectedCdnId].size() < 1) 486 | { 487 | continue; 488 | } 489 | ranTMP = rand() / double(RAND_MAX); 490 | while(ranTMP == 1) 491 | { 492 | ranTMP = rand() / double(RAND_MAX); 493 | } 494 | int ran2 = (int)(ranTMP * userNeighbors[ranSelectedCdnId].size()); 495 | int ranSelectedCdnId2 = userNeighbors[ranSelectedCdnId][ran2]; 496 | vector::iterator it = find(newCDNNdIds.begin(), newCDNNdIds.end(), ranSelectedCdnId2); 497 | if(it != newCDNNdIds.end()) 498 | { 499 | continue; 500 | } 501 | newCDNNdIds.erase(ran + newCDNNdIds.begin()); 502 | newCDNNdIds.push_back(ranSelectedCdnId2); 503 | break; 504 | } 505 | } 506 | } 507 | void nearSolusionMORE(vector& lastCdnNdIds, vector& fixedCdnIds, int countForMore) 508 | { 509 | newCDNNdIds.clear(); 510 | newCDNNdIds.reserve(lastCdnNdIds.size()); 511 | newCDNNdIds.insert(newCDNNdIds.end(), lastCdnNdIds.begin(), lastCdnNdIds.end()); 512 | int ran, ranSelectedCdnId; 513 | double ranTMP; 514 | for(int i = 0; i < countForMore; i++) 515 | { 516 | while(true) 517 | { 518 | if(lastCdnNdIds.size() >= userNum) 519 | { 520 | printf("It's Fulllllll!!! \n"); 521 | return; 522 | } 523 | ranTMP = rand() / double(RAND_MAX); 524 | while(ranTMP == 1) 525 | { 526 | ranTMP = rand() / double(RAND_MAX); 527 | } 528 | ran = (int)(ranTMP * userNum); 529 | ranSelectedCdnId = map_UserToNd[ran]; 530 | vector::iterator it = find(newCDNNdIds.begin(), newCDNNdIds.end(), ranSelectedCdnId); 531 | if(it != newCDNNdIds.end()) 532 | { 533 | continue; 534 | } 535 | else 536 | { 537 | newCDNNdIds.push_back(ranSelectedCdnId); 538 | break; 539 | } 540 | } 541 | } 542 | } 543 | 544 | void setAllNeighbors() 545 | { 546 | for(int i = 0; i < nodeNum; i++) 547 | { 548 | for(int j = 0; j < nodes[i].size(); j++) 549 | { 550 | Edge& e = edges[nodes[i][j]]; 551 | if(e.cost > 0) 552 | { 553 | neighbors[i].push_back(e.endNd); 554 | if(map_NdToUser[e.endNd] != -1) 555 | { 556 | userNeighbors[i].push_back(e.endNd); 557 | } 558 | } 559 | } 560 | } 561 | } 562 | 563 | void handler(int sig) 564 | { 565 | //printf("正在输出结果!!!!"); 566 | //buildTopoResult(topo_file); 567 | //write_result((char *)topo_file.data(), result_file); 568 | //exit(0); 569 | run = false; 570 | } 571 | 572 | void selfishness(vector& nodeIds, int tolerance) 573 | { 574 | for(int i = 0; i < userNum; i++) 575 | { 576 | map links; 577 | vector& node = nodes[map_UserToNd[i]]; 578 | 579 | for(int j = 0; j < node.size(); j++) 580 | { 581 | Edge& edge = edges[node[j]]; 582 | if(edge.cost > 0) 583 | { 584 | map::iterator it = links.find(edge.cost); 585 | if(it != links.end()) 586 | { 587 | links.insert(pair(edge.cost, links.at(edge.cost) + edge.capacity)); 588 | } 589 | else 590 | { 591 | links.insert(pair(edge.cost, edge.capacity)); 592 | } 593 | } 594 | } 595 | 596 | // map::iterator x = links.begin(); 597 | // while(x != links.end()) 598 | // { 599 | // printf("-------first %d---second %d---\n", x->first, x->second); 600 | // x++; 601 | // } 602 | // printf("---------------------------------\n"); 603 | int curUserReq = user_req[i]; 604 | int leastCost = 0; 605 | map::iterator itor = links.begin(); 606 | while(itor != links.end()) 607 | { 608 | //printf("--4-----second %d---first %d---\n", itor->second, itor->first); 609 | curUserReq -= itor->second; 610 | leastCost += itor->first * itor->second; 611 | if(curUserReq == 0) break; 612 | if(curUserReq < 0) 613 | { 614 | leastCost -= (-curUserReq) * (itor->first); 615 | break; 616 | } 617 | itor++; 618 | } 619 | 620 | if(leastCost >= cdnCost - tolerance) 621 | { 622 | if(tolerance == 0) 623 | { 624 | realCDN[map_UserToNd[i]] = true; 625 | printf("\n---realCDN---%d------\n\n", realCDN[map_UserToNd[i]]); 626 | } 627 | nodeIds.push_back(map_UserToNd[i]); 628 | } 629 | 630 | } 631 | } 632 | 633 | bool SPFA(int startNd, int endNd, int& cost, int& flow, vector& paths) 634 | { 635 | int end = nodeNum + 2; 636 | for(int i = 0; i < end; i++) 637 | { 638 | disTo[i] = MAX_Int; 639 | edgeTo[i] = -1; 640 | aug[i] = 0; 641 | inQ[i] = 0; 642 | } 643 | 644 | disTo[startNd] = 0; 645 | aug[startNd] = MAX_Int; 646 | inQ[startNd] = 1; 647 | deque Q; 648 | Q.push_back(startNd); 649 | while(!Q.empty()) 650 | { 651 | int nodeId = Q.front(); 652 | Q.pop_front(); 653 | inQ[nodeId]--; 654 | for(int i = 0; i < nodes[nodeId].size(); i++) 655 | { 656 | Edge& e = edges[nodes[nodeId][i]]; 657 | if(e.capacity > e.flow && (disTo[e.endNd] > disTo[nodeId] + e.cost)) 658 | { 659 | disTo[e.endNd] = disTo[nodeId] + e.cost; 660 | edgeTo[e.endNd] = nodes[nodeId][i]; 661 | aug[e.endNd] = min(aug[nodeId], e.capacity - e.flow); 662 | if(!inQ[e.endNd]) 663 | { 664 | inQ[e.endNd]++; 665 | if(Q.empty()) 666 | { 667 | Q.push_back(e.endNd); 668 | } 669 | else 670 | { 671 | if(disTo[e.endNd] >= disTo[Q.front()]) 672 | { 673 | Q.push_back(e.endNd); 674 | } 675 | else 676 | { 677 | Q.push_front(e.endNd); 678 | } 679 | } 680 | } 681 | } 682 | } 683 | } 684 | if(disTo[endNd] == MAX_Int) return false; 685 | flow = aug[endNd]; 686 | cost = disTo[endNd]; 687 | int indexNd = endNd; 688 | 689 | while(indexNd != startNd) 690 | { 691 | edges[edgeTo[indexNd]].flow += aug[endNd]; 692 | edges[edgeTo[indexNd]^1].flow -= aug[endNd]; 693 | paths.push_back(edgeTo[indexNd]); 694 | indexNd = edges[edgeTo[indexNd]].startNd; 695 | } 696 | return true; 697 | } 698 | 699 | int MinCostMaxFlowSA(vector& nodeIds) 700 | { 701 | addSuperSourceEdges(nodeIds); 702 | // printf("\n"); 703 | // printf("%d\n", totalReq); 704 | // printf("\n"); 705 | int totalCost = MinCostMaxFlow(superSourceId, superSinkId, totalReq); 706 | cleanSuperSourceEdges(nodeIds); 707 | 708 | int end = edges.size(); 709 | for(int i = 0; i < end; i++) 710 | { 711 | edges[i].flow = 0; 712 | } 713 | 714 | return totalCost; 715 | } 716 | 717 | int MinCostMaxFlow(int startNd, int endNd, int neededFlow) 718 | { 719 | int flowCost = 0; 720 | int countFlow = neededFlow; 721 | int cost = 0, flow = 0; 722 | vector paths; 723 | while(SPFA(startNd, endNd, cost, flow, paths)) 724 | { 725 | flowCost += cost * flow; 726 | countFlow -= flow; 727 | // printf("%d ", flowCost); 728 | // printf("%d \n", countFlow); 729 | 730 | if(countFlow < 0) 731 | { 732 | int end = paths.size(); 733 | for(int i = 0; i < end; i++) 734 | { 735 | edges[paths[i]].flow += countFlow; 736 | edges[paths[i]^1].flow -= countFlow; 737 | } 738 | flowCost += countFlow * cost; 739 | break; 740 | } 741 | if(countFlow == 0) 742 | { 743 | break; 744 | } 745 | cost = 0; 746 | flow = 0; 747 | paths.clear(); 748 | } 749 | if(countFlow > 0) return -1; 750 | int totalCost = flowCost + cdnCost * nodes[superSourceId].size(); 751 | 752 | if(totalCost < bestCost) 753 | { 754 | bestCost = totalCost; 755 | getBestPaths(); 756 | // printf("%d\n", bestPaths.size()); 757 | // for(int i = 0; i < bestPaths.size(); i++) 758 | // { 759 | // printf("%s\n", bestPaths[i].data()); 760 | // } 761 | } 762 | return totalCost; 763 | } 764 | 765 | void getBestPaths() 766 | { 767 | bestPaths.clear(); 768 | int end = nodes[superSourceId].size(); 769 | for(int i = 0; i < end; i++) 770 | { 771 | Edge& edge = edges[nodes[superSourceId][i]]; 772 | string pathString = to_string(edge.endNd); 773 | getBestPathByDFS(edge, edge.flow, pathString); 774 | } 775 | } 776 | 777 | int getBestPathByDFS(Edge& edge, int minFlow, string& pathString) 778 | { 779 | int newMinFlow = min(minFlow, edge.flow); 780 | int tmp = newMinFlow; 781 | if(edge.endNd == superSinkId) 782 | { 783 | pathString += " "; 784 | pathString += to_string(map_NdToUser[edge.startNd]); 785 | pathString += " "; 786 | pathString += to_string(newMinFlow); 787 | bestPaths.push_back(pathString); 788 | return newMinFlow; 789 | } 790 | int end = nodes[edge.endNd].size(); 791 | for(int i = 0; i < end; i++) 792 | { 793 | Edge& subEdge = edges[nodes[edge.endNd][i]]; 794 | if(subEdge.cost >= 0 && subEdge.flow > 0) 795 | { 796 | string subParhString = pathString; 797 | if(subEdge.endNd != superSinkId) 798 | { 799 | subParhString += " "; 800 | subParhString += to_string(subEdge.endNd); 801 | } 802 | int flwCost = getBestPathByDFS(subEdge, tmp, subParhString); 803 | tmp -= flwCost; 804 | if(tmp == 0) break; 805 | } 806 | } 807 | edge.flow -= newMinFlow; 808 | return newMinFlow; 809 | } 810 | 811 | void addSuperSinkEdges() 812 | { 813 | for(int i = 0; i < userNum; i++) 814 | { 815 | edges.push_back(Edge(map_UserToNd[i], superSinkId, user_req[i], 0, 0)); 816 | edges.push_back(Edge(superSinkId, map_UserToNd[i], 0, 0, 0)); 817 | int m = edges.size(); 818 | nodes[map_UserToNd[i]].push_back(m - 2); 819 | nodes[superSinkId].push_back(m - 1); 820 | } 821 | } 822 | 823 | void addSuperSourceEdges(vector& CDNs) 824 | { 825 | int end = CDNs.size(); 826 | for(int i = 0; i < end; i++) 827 | { 828 | edges.push_back(Edge(superSourceId, CDNs[i], MAX_Int, 0, 0)); 829 | edges.push_back(Edge(CDNs[i], superSourceId, 0, 0, 0)); 830 | int m = edges.size(); 831 | nodes[superSourceId].push_back(m - 2); 832 | nodes[CDNs[i]].push_back(m - 1); 833 | } 834 | } 835 | 836 | void cleanSuperSourceEdges(vector& CDNs) 837 | { 838 | int end = CDNs.size(); 839 | for(int i = 0; i < end; i++) 840 | { 841 | nodes[CDNs[i]].pop_back(); 842 | } 843 | int begId = nodes[superSourceId][0]; 844 | edges.erase(edges.begin() + begId, edges.end()); 845 | nodes[superSourceId].clear(); 846 | } 847 | 848 | char * charToNum(char * str, int& target) 849 | { 850 | int sum = 0; 851 | while(((*str) != 32) && ((*str) != 13) && ((*str) != 0)) 852 | { 853 | sum = sum * 10 + ((*str) - '0'); 854 | str++; 855 | } 856 | target = sum; 857 | return ++str; 858 | } 859 | 860 | void buildTopoResult(string& result) 861 | { 862 | int end = bestPaths.size(); 863 | result = to_string(end); 864 | result += "\n\n"; 865 | for(int i = 0; i < end; i++) 866 | { 867 | result += bestPaths[i]; 868 | if(i != (end - 1)) result += "\n"; 869 | } 870 | } 871 | 872 | -------------------------------------------------------------------------------- /退火+ SPFA by C++/cdn/deploy.h: -------------------------------------------------------------------------------- 1 | #ifndef __ROUTE_H__ 2 | #define __ROUTE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "lib_io.h" 17 | 18 | #define MAX_NODE_NUM 1000 19 | #define MAX_DEGREE_NUM 20 20 | #define MAX_USER_NUM 500 21 | #define MAX_PRICE 100 22 | #define MAX_CAPACITY 100 23 | #define MAX_CDN_COST 5000 24 | #define MAX_REQ 5000 25 | 26 | using namespace std; 27 | 28 | struct Edge 29 | { 30 | int startNd; 31 | int endNd; 32 | int capacity; 33 | int cost; 34 | int flow; 35 | Edge(int u, int v, int ca, int cst, int fl):startNd(u), endNd(v), capacity(ca), cost(cst), flow(fl){}; 36 | }; 37 | 38 | void deploy_server(char * graph[MAX_EDGE_NUM], int edge_num, char * filename); 39 | void handler(int sig); 40 | 41 | void Fire(double cT, double dC, int inter, int outer, double ratio); 42 | void fireAlgo(vector& cdnNdIds, vector& fixedCdnIds, int countForLess, int caseKind, int countFormore, double lessOrMore); 43 | void nearSolusionLESS(vector& lastCdnNdIds, vector& fixedCdnIds, int countForLess, int caseKind); 44 | void nearSolusionKEEP(vector& lastCdnNdIds, vector& fixedCdnIds, int countForKeep); 45 | void nearSolusionMORE(vector& lastCdnNdIds, vector& fixedCdnIds, int countForMore); 46 | 47 | void setAllNeighbors(); 48 | 49 | bool SPFA(int startNd, int endNd, int& cost, int& flow); 50 | int MinCostMaxFlow(int startNd, int endNd, int neededFlow); 51 | int MinCostMaxFlowSA(vector& nodeIds); 52 | void selfishness(vector& nodeIds, int tolerance); 53 | 54 | void getBestPaths(); 55 | int getBestPathByDFS(Edge& edge, int minFlow, string& pathString); 56 | 57 | void addSuperSinkEdges(); 58 | void addSuperSourceEdges(vector& CDNs); 59 | void cleanSuperSourceEdges(vector& CDNs); 60 | 61 | char * charToNum(char * str, int& target); 62 | void buildTopoResult(string& result); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /退火+ SPFA by C++/cdn/io.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAX_LINE_LEN 55000 12 | 13 | #define INLINE static __inline 14 | #ifdef _DEBUG 15 | #define PRINT printf 16 | #else 17 | #define PRINT(...) 18 | #endif 19 | 20 | 21 | INLINE void write_file(const bool cover, const char * const buff, const char * const filename); 22 | 23 | 24 | void print_time(const char *head) 25 | { 26 | #ifdef _DEBUG 27 | struct timeb rawtime; 28 | struct tm * timeinfo; 29 | ftime(&rawtime); 30 | timeinfo = localtime(&rawtime.time); 31 | 32 | static int ms = rawtime.millitm; 33 | static unsigned long s = rawtime.time; 34 | int out_ms = rawtime.millitm - ms; 35 | unsigned long out_s = rawtime.time - s; 36 | ms = rawtime.millitm; 37 | s = rawtime.time; 38 | 39 | if (out_ms < 0) 40 | { 41 | out_ms += 1000; 42 | out_s -= 1; 43 | } 44 | printf("%s date/time is: %s \tused time is %lu s %d ms.\n", head, asctime(timeinfo), out_s, out_ms); 45 | #endif 46 | } 47 | 48 | int read_file(char ** const buff, const unsigned int spec, const char * const filename) 49 | { 50 | FILE *fp = fopen(filename, "r"); 51 | if (fp == NULL) 52 | { 53 | PRINT("Fail to open file %s, %s.\n", filename, strerror(errno)); 54 | return 0; 55 | } 56 | PRINT("Open file %s OK.\n", filename); 57 | 58 | char line[MAX_LINE_LEN + 2]; 59 | unsigned int cnt = 0; 60 | while ((cnt < spec) && !feof(fp)) 61 | { 62 | line[0] = 0; 63 | if (fgets(line, MAX_LINE_LEN + 2, fp) == NULL) continue; 64 | if (line[0] == 0) continue; 65 | buff[cnt] = (char *)malloc(MAX_LINE_LEN + 2); 66 | strncpy(buff[cnt], line, MAX_LINE_LEN + 2 - 1); 67 | buff[cnt][MAX_LINE_LEN + 1] = 0; 68 | cnt++; 69 | } 70 | fclose(fp); 71 | PRINT("There are %d lines in file %s.\n", cnt, filename); 72 | 73 | return cnt; 74 | } 75 | 76 | void write_result(const char * const buff,const char * const filename) 77 | { 78 | // 以覆盖的方式写入 79 | write_file(1, buff, filename); 80 | 81 | } 82 | 83 | void release_buff(char ** const buff, const int valid_item_num) 84 | { 85 | for (int i = 0; i < valid_item_num; i++) 86 | free(buff[i]); 87 | } 88 | 89 | INLINE void write_file(const bool cover, const char * const buff, const char * const filename) 90 | { 91 | if (buff == NULL) 92 | return; 93 | 94 | const char *write_type = cover ? "w" : "a";//1:覆盖写文件,0:追加写文件 95 | FILE *fp = fopen(filename, write_type); 96 | if (fp == NULL) 97 | { 98 | PRINT("Fail to open file %s, %s.\n", filename, strerror(errno)); 99 | return; 100 | } 101 | PRINT("Open file %s OK.\n", filename); 102 | fputs(buff, fp); 103 | fputs("\n", fp); 104 | fclose(fp); 105 | } 106 | 107 | -------------------------------------------------------------------------------- /退火+ SPFA by C++/cdn/lib/lib_io.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIB_IO_H__ 2 | #define __LIB_IO_H__ 3 | 4 | #define MAX_EDGE_NUM (2000 * 20) 5 | 6 | //读取文件并按行输出到buff。 7 | //buff为一个指针数组,每一个元素是一个字符指针,对应文件中一行的内容。 8 | //spec为允许解析的最大行数。 9 | extern int read_file(char ** const buff, const unsigned int spec, const char * const filename); 10 | 11 | //将result缓冲区中的内容写入文件,写入方式为覆盖写入 12 | extern void write_result(const char * const buff,const char * const filename); 13 | 14 | //释放读文件的缓冲区 15 | extern void release_buff(char ** const buff, const int valid_item_num); 16 | 17 | #endif 18 | 19 | -------------------------------------------------------------------------------- /退火+ SPFA by C++/cdn/lib/lib_time.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIB_TIME_H__ 2 | #define __LIB_TIME_H__ 3 | 4 | //打印时间。入参为打印信息头 5 | void print_time(const char * const head); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /退火+ SPFA by C++/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by C++/readme.txt -------------------------------------------------------------------------------- /退火+ SPFA by Java/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /退火+ SPFA by Java/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2017HUAWEIcodecraft 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /退火+ SPFA by Java/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /退火+ SPFA by Java/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/ConUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/ConUtil.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/Deploy.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/Deploy.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/Edge.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/Edge.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/FileUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/FileUtil.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/Fire.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/Fire.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/GraphAlgo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/GraphAlgo.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/LogUtil$Time.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/LogUtil$Time.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/LogUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/LogUtil.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/Main.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/Main.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/NetworkGraph.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/NetworkGraph.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/Node.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/Node.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/Path.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/Path.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/Timer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/Timer.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/User.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/User.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/bin/com/Users.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANYUQI/2017HuaweiCodeCraft/50e16858a6532e7b46032788a21f579a249ff5db/退火+ SPFA by Java/bin/com/Users.class -------------------------------------------------------------------------------- /退火+ SPFA by Java/src/com/ConUtil.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | public class ConUtil { 4 | public final static int MAX_NODE_NUM = 1000; 5 | public final static int MAX_DEGREE_NUM = 20; 6 | public final static int MAX_USER_NUM = 500; 7 | public final static int MAX_PRICE = 100; 8 | public final static int MAX_CAPCITY = 100; 9 | public final static int MAX_CDN_COST = 5000; 10 | public final static int MAX_REQ = 5000; 11 | } 12 | -------------------------------------------------------------------------------- /退火+ SPFA by Java/src/com/Deploy.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | 7 | 8 | 9 | public class Deploy { 10 | public static String[] deployServer(String[] graphContent) 11 | { 12 | Timer timer = new Timer(); 13 | timer.begin(); 14 | 15 | NetworkGraph networkGraph; 16 | 17 | String[] tmp = graphContent[0].split(" "); 18 | int[] graphInfo = new int[tmp.length]; 19 | for(int i = 0; i < 3; i++) 20 | { 21 | graphInfo[i] = Integer.parseInt(tmp[i]); 22 | } 23 | 24 | networkGraph = new NetworkGraph(graphInfo[0], graphInfo[1], graphInfo[2]); 25 | 26 | int cdnCost = Integer.parseInt(graphContent[2]); 27 | 28 | networkGraph.setCDNcost(cdnCost); 29 | 30 | int count = 4; 31 | for(int i = 1; i <= networkGraph.edgeNum; i++) 32 | { 33 | String[] edgeTmp = graphContent[count++].split(" "); 34 | int startNd = Integer.parseInt(edgeTmp[0]); 35 | int endNd = Integer.parseInt(edgeTmp[1]); 36 | int capacity = Integer.parseInt(edgeTmp[2]); 37 | int price = Integer.parseInt(edgeTmp[3]); 38 | boolean added = networkGraph.addEdge(startNd, endNd, capacity, price); 39 | 40 | } 41 | 42 | count++; 43 | 44 | for(int j = 1; j <= networkGraph.users.userNum; j++) 45 | { 46 | String[] userTmp = graphContent[count++].split(" "); 47 | int id = Integer.parseInt(userTmp[0]); 48 | int linkedNodeID = Integer.parseInt(userTmp[1]); 49 | int reqBandwidth = Integer.parseInt(userTmp[2]); 50 | 51 | networkGraph.users.addUser(id, linkedNodeID, reqBandwidth); 52 | networkGraph.nodes.get(linkedNodeID).userId = id; 53 | } 54 | 55 | networkGraph.setAllNeighbors(); 56 | 57 | GraphAlgo graphAlgo = new GraphAlgo(networkGraph.nodeNum + 2); 58 | 59 | 60 | 61 | 62 | if(networkGraph.nodeNum < 200 ){ 63 | 64 | timer.setThreshold(88500); 65 | 66 | int toleranceForCandidates = 600; 67 | int toleranceForFixed = 0; 68 | ArrayList cdnNodeIds; 69 | 70 | networkGraph.addSuperSinkEdges(); 71 | while(true){ 72 | cdnNodeIds = graphAlgo.selfishness(networkGraph,toleranceForCandidates); 73 | int tmpCost = graphAlgo.MincostMaxflowForGA(networkGraph, cdnNodeIds,timer); 74 | if(tmpCost < 0 ) { 75 | System.out.println("初始解不可行,tolerance += 50,重新产生中》》》"); 76 | toleranceForCandidates += 50; 77 | continue; 78 | }else{ 79 | System.out.println("初始解可行!!!开始退火!"); 80 | break; 81 | } 82 | } 83 | ArrayList fixedCdnIds = graphAlgo.selfishness(networkGraph,toleranceForFixed); 84 | 85 | System.out.println("fixedCdnIds: "+fixedCdnIds.size()+" 个 "+fixedCdnIds.toString()); 86 | System.out.println("cdnNodeIds: "+cdnNodeIds.size()+" 个 "+cdnNodeIds.toString()); 87 | 88 | 89 | Fire fire = new Fire(2,0.997,50,100,0.00001); 90 | fire.fireAlg(cdnNodeIds,fixedCdnIds,networkGraph, graphAlgo,timer,1,0,1,0.75); 91 | 92 | }else if(networkGraph.nodeNum < 400){ 93 | 94 | timer.setThreshold(88500); 95 | 96 | 97 | int toleranceForCandidates = 600; 98 | int toleranceForFixed = 0; 99 | ArrayList cdnNodeIds; 100 | 101 | networkGraph.addSuperSinkEdges(); 102 | while(true){ 103 | cdnNodeIds = graphAlgo.selfishness(networkGraph,toleranceForCandidates); 104 | System.out.println("cdnNodeIds: "+cdnNodeIds.size()+" 个 "+cdnNodeIds.toString()); 105 | 106 | int tmpCost = graphAlgo.MincostMaxflowForGA(networkGraph, cdnNodeIds,timer); 107 | if(tmpCost < 0 ) { 108 | System.out.println("初始解不可行,tolerance += 50,重新产生中》》》"); 109 | toleranceForCandidates += 50; 110 | continue; 111 | }else{ 112 | System.out.println("初始解可行!!!开始退火!"); 113 | break; 114 | } 115 | } 116 | ArrayList fixedCdnIds = graphAlgo.selfishness(networkGraph,toleranceForFixed); 117 | 118 | Fire fire = new Fire(5,1,50,100,0.1); 119 | fire.fireAlg(cdnNodeIds,fixedCdnIds,networkGraph, graphAlgo,timer,1,1,1,0.75); 120 | 121 | }else{ 122 | 123 | timer.setThreshold(87500); 124 | 125 | int toleranceForCandidates = 900; 126 | int toleranceForFixed = 750; 127 | ArrayList cdnNodeIds; 128 | 129 | networkGraph.addSuperSinkEdges(); 130 | while(true){ 131 | cdnNodeIds = graphAlgo.selfishness(networkGraph,toleranceForCandidates); 132 | System.out.println("cdnNodeIds: "+cdnNodeIds.size()+" 个 "+cdnNodeIds.toString()); 133 | int tmpCost = graphAlgo.MincostMaxflowForGA(networkGraph, cdnNodeIds,timer); 134 | if(tmpCost < 0 ) { 135 | System.out.println("初始解不可行,tolerance += 50,重新产生中》》》"); 136 | toleranceForCandidates += 50; 137 | 138 | continue; 139 | }else{ 140 | System.out.println("初始解可行!!!开始退火!"); 141 | break; 142 | } 143 | } 144 | ArrayList fixedCdnIds = graphAlgo.selfishness(networkGraph,toleranceForFixed); 145 | System.out.println("fixedCdnIds: "+fixedCdnIds.size()+" 个 "+fixedCdnIds.toString()); 146 | 147 | 148 | Fire fire = new Fire(10,0.997,40,100,0.1); 149 | 150 | int countLess = 0; 151 | if(cdnNodeIds.size()<200){ 152 | countLess = 6; 153 | }else{ 154 | countLess = 9; 155 | } 156 | fire.fireAlg(cdnNodeIds,fixedCdnIds,networkGraph, graphAlgo,timer,countLess,2,1,0.99);//2,2,1 157 | 158 | } 159 | 160 | 161 | System.out.println(GraphAlgo.bestCost); 162 | System.out.println(GraphAlgo.bestPathList.size()); 163 | System.out.println(GraphAlgo.bestPathList.toString()); 164 | 165 | 166 | List pathsInfo = GraphAlgo.bestPathList; 167 | String[] resultContents = new String[pathsInfo.size() + 2]; 168 | resultContents[0] = String.valueOf(pathsInfo.size()); 169 | resultContents[1] = ""; 170 | for (int i = 0; i < pathsInfo.size(); i++) { 171 | resultContents[i + 2] = pathsInfo.get(i); 172 | } 173 | 174 | timer.print(); 175 | 176 | return resultContents; 177 | 178 | } 179 | 180 | 181 | 182 | public static void main(String[] args) { 183 | 184 | String graphFilePath = "D:/casesNew/low/case0.txt"; 185 | String resultFilePath = "D:/answers/answer.txt"; 186 | 187 | String[] graphContent = FileUtil.read(graphFilePath, null); 188 | String[] resultContents = Deploy.deployServer(graphContent); 189 | 190 | if (hasResults(resultContents)) 191 | { 192 | FileUtil.write(resultFilePath, resultContents, false); 193 | } 194 | else 195 | { 196 | FileUtil.write(resultFilePath, new String[] { "NA" }, false); 197 | } 198 | LogUtil.printLog("End"); 199 | } 200 | 201 | private static boolean hasResults(String[] resultContents) 202 | { 203 | if(resultContents==null) 204 | { 205 | return false; 206 | } 207 | for (String contents : resultContents) 208 | { 209 | if (contents != null && !contents.trim().isEmpty()) 210 | { 211 | return true; 212 | } 213 | } 214 | return false; 215 | } 216 | 217 | } 218 | -------------------------------------------------------------------------------- /退火+ SPFA by Java/src/com/FileUtil.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.BufferedWriter; 5 | import java.io.Closeable; 6 | import java.io.File; 7 | import java.io.FileReader; 8 | import java.io.FileWriter; 9 | import java.io.IOException; 10 | import java.util.LinkedList; 11 | import java.util.List; 12 | 13 | public final class FileUtil 14 | { 15 | 16 | public static String[] read(final String filePath, final Integer spec) 17 | { 18 | File file = new File(filePath); 19 | // 当文件不存在或者不可读时 20 | if ((!isFileExists(file)) || (!file.canRead())) 21 | { 22 | System.out.println("file [" + filePath + "] is not exist or cannot read!!!"); 23 | return null; 24 | } 25 | 26 | List lines = new LinkedList(); 27 | BufferedReader br = null; 28 | FileReader fb = null; 29 | try 30 | { 31 | fb = new FileReader(file); 32 | br = new BufferedReader(fb); 33 | 34 | String str = null; 35 | int index = 0; 36 | while (((spec == null) || index++ < spec) && (str = br.readLine()) != null) 37 | { 38 | lines.add(str); 39 | } 40 | } 41 | catch (IOException e) 42 | { 43 | e.printStackTrace(); 44 | } 45 | finally 46 | { 47 | closeQuietly(br); 48 | closeQuietly(fb); 49 | } 50 | 51 | return lines.toArray(new String[lines.size()]); 52 | } 53 | 54 | public static int write(final String filePath, final String[] contents, final boolean append) 55 | { 56 | File file = new File(filePath); 57 | if (contents == null) 58 | { 59 | System.out.println("file [" + filePath + "] invalid!!!"); 60 | return 0; 61 | } 62 | 63 | // 当文件存在但不可写时 64 | if (isFileExists(file) && (!file.canRead())) 65 | { 66 | return 0; 67 | } 68 | 69 | FileWriter fw = null; 70 | BufferedWriter bw = null; 71 | try 72 | { 73 | if (!isFileExists(file)) 74 | { 75 | file.createNewFile(); 76 | } 77 | 78 | fw = new FileWriter(file, append); 79 | bw = new BufferedWriter(fw); 80 | for (String content : contents) 81 | { 82 | if (content == null) 83 | { 84 | continue; 85 | } 86 | bw.write(content); 87 | bw.newLine(); 88 | } 89 | } 90 | catch (IOException e) 91 | { 92 | e.printStackTrace(); 93 | return 0; 94 | } 95 | finally 96 | { 97 | closeQuietly(bw); 98 | closeQuietly(fw); 99 | } 100 | 101 | return 1; 102 | } 103 | 104 | private static void closeQuietly(Closeable closeable) 105 | { 106 | try 107 | { 108 | if (closeable != null) 109 | { 110 | closeable.close(); 111 | } 112 | } 113 | catch (IOException e) 114 | { 115 | } 116 | } 117 | 118 | private static boolean isFileExists(final File file) 119 | { 120 | if (file.exists() && file.isFile()) 121 | { 122 | return true; 123 | } 124 | 125 | return false; 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /退火+ SPFA by Java/src/com/Fire.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class Fire { 6 | 7 | private double curT; 8 | private double deCold; 9 | private int interTimes; 10 | private int outerTimes; 11 | private double p; 12 | private ArrayList newCdnNodeIds; 13 | 14 | 15 | public Fire(double curT1,double deCold1,int interTimes1,int outerTimes1,double p1){ 16 | this.curT = curT1; 17 | this.deCold = deCold1; 18 | this.interTimes = interTimes1; 19 | this.outerTimes = outerTimes1; 20 | this.p = p1; 21 | this.newCdnNodeIds = new ArrayList(); 22 | } 23 | 24 | public void fireAlg(ArrayList cdnNodeIds,ArrayList fixedCdnIds,NetworkGraph g, GraphAlgo graphAlgo,Timer t,int countForLess,int caseKind,int countForMore,double lessOrMore){ 25 | 26 | int countForLessTMP = countForLess; 27 | double lessOrMoreTMP = lessOrMore; 28 | 29 | ArrayList lastCdnNodeIds = new ArrayList(); 30 | lastCdnNodeIds.addAll(cdnNodeIds); 31 | int lastCost = GraphAlgo.bestCost; 32 | 33 | ArrayList curCdnNodeIds = new ArrayList(); 34 | int curCost; 35 | 36 | double ran; 37 | double metropolis; 38 | 39 | 40 | boolean tmpB = true; 41 | 42 | int countTimes = 0; 43 | int unacTimes = 0; 44 | for(int curOuterTimes = 0;curOuterTimes < this.outerTimes;curOuterTimes++){ 45 | 46 | for(int curInterTimes = 0;curInterTimes < this.interTimes;curInterTimes++){ 47 | 48 | while(true){ 49 | 50 | if(t.overtime()) return; 51 | 52 | if(caseKind == 2 ) { 53 | 54 | 55 | if(lastCdnNodeIds.size()<150){ 56 | countForLessTMP = 1; 57 | 58 | 59 | ran = Math.random(); 60 | if(ran < 0.6 ){ 61 | curCdnNodeIds.clear(); 62 | this.nearSolutionLESS(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForLessTMP,caseKind); 63 | curCdnNodeIds.addAll(this.newCdnNodeIds); 64 | } 65 | else if (ran < 0.8) { 66 | curCdnNodeIds.clear(); 67 | this.nearSolutionMORE(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForMore); 68 | curCdnNodeIds.addAll(this.newCdnNodeIds); 69 | }else{ 70 | curCdnNodeIds.clear(); 71 | this.nearSolutionKeep(lastCdnNodeIds,fixedCdnIds,g,1); 72 | curCdnNodeIds.addAll(this.newCdnNodeIds); 73 | } 74 | }else{ 75 | ran = Math.random(); 76 | if(ran < lessOrMoreTMP ){ 77 | curCdnNodeIds.clear(); 78 | this.nearSolutionLESS(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForLessTMP,caseKind); 79 | curCdnNodeIds.addAll(this.newCdnNodeIds); 80 | } 81 | else { 82 | curCdnNodeIds.clear(); 83 | this.nearSolutionMORE(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForMore); 84 | curCdnNodeIds.addAll(this.newCdnNodeIds); 85 | } 86 | } 87 | 88 | } 89 | else if(caseKind == 1){ 90 | 91 | if(lastCdnNodeIds.size()<60){ 92 | countForLessTMP = 1; 93 | 94 | ran = Math.random(); 95 | if(ran < 0.6 ){ 96 | curCdnNodeIds.clear(); 97 | this.nearSolutionLESS(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForLessTMP,caseKind); 98 | curCdnNodeIds.addAll(this.newCdnNodeIds); 99 | } 100 | else if (ran < 0.8) { 101 | curCdnNodeIds.clear(); 102 | this.nearSolutionMORE(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForMore); 103 | curCdnNodeIds.addAll(this.newCdnNodeIds); 104 | }else{ 105 | curCdnNodeIds.clear(); 106 | this.nearSolutionKeep(lastCdnNodeIds,fixedCdnIds,g,1); 107 | curCdnNodeIds.addAll(this.newCdnNodeIds); 108 | } 109 | }else{ 110 | ran = Math.random(); 111 | if(ran < lessOrMoreTMP ){ 112 | curCdnNodeIds.clear(); 113 | this.nearSolutionLESS(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForLessTMP,caseKind); 114 | curCdnNodeIds.addAll(this.newCdnNodeIds); 115 | } 116 | else{ 117 | curCdnNodeIds.clear(); 118 | this.nearSolutionMORE(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForMore); 119 | curCdnNodeIds.addAll(this.newCdnNodeIds); 120 | 121 | } 122 | } 123 | 124 | 125 | 126 | 127 | } 128 | else if(caseKind == 0){ 129 | 130 | if(GraphAlgo.bestCost <= 28876){ 131 | tmpB = false; 132 | } 133 | if(tmpB){ 134 | 135 | if(lastCdnNodeIds.size()<40){ 136 | countForLessTMP = 1; 137 | ran = Math.random(); 138 | if(ran < 0.6 ){ 139 | curCdnNodeIds.clear(); 140 | this.nearSolutionLESS(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForLessTMP,caseKind); 141 | curCdnNodeIds.addAll(this.newCdnNodeIds); 142 | } 143 | else if (ran < 0.8) { 144 | curCdnNodeIds.clear(); 145 | this.nearSolutionMORE(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForMore); 146 | curCdnNodeIds.addAll(this.newCdnNodeIds); 147 | }else{ 148 | curCdnNodeIds.clear(); 149 | this.nearSolutionKeep(lastCdnNodeIds,fixedCdnIds,g,1); 150 | curCdnNodeIds.addAll(this.newCdnNodeIds); 151 | } 152 | }else{ 153 | ran = Math.random(); 154 | if(ran > lessOrMore ){ 155 | curCdnNodeIds.clear(); 156 | this.nearSolutionMORE(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForMore); 157 | curCdnNodeIds.addAll(this.newCdnNodeIds); 158 | } 159 | else{ 160 | curCdnNodeIds.clear(); 161 | this.nearSolutionLESS(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForLessTMP,caseKind); 162 | curCdnNodeIds.addAll(this.newCdnNodeIds); 163 | } 164 | } 165 | 166 | }else{ 167 | 168 | ran = Math.random(); 169 | if(ran < 0.5 ){ 170 | curCdnNodeIds.clear(); 171 | this.nearSolutionLESS(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForLessTMP,caseKind); 172 | curCdnNodeIds.addAll(this.newCdnNodeIds); 173 | } 174 | else if (ran < 0.75) { 175 | curCdnNodeIds.clear(); 176 | this.nearSolutionMOREforLow(lastCdnNodeIds,fixedCdnIds,g,graphAlgo,countForMore); 177 | curCdnNodeIds.addAll(this.newCdnNodeIds); 178 | }else{ 179 | curCdnNodeIds.clear(); 180 | this.nearSolutionKeepforLow(lastCdnNodeIds,fixedCdnIds,g,1); 181 | curCdnNodeIds.addAll(this.newCdnNodeIds); 182 | } 183 | } 184 | } 185 | 186 | 187 | countTimes++; 188 | System.out.println("***************以下是第:"+ countTimes +"***************"); 189 | 190 | 191 | curCost = graphAlgo.MincostMaxflowForGA(g, curCdnNodeIds,t); 192 | if(curCost == -1) { 193 | unacTimes++; 194 | System.out.println("Not available! Continue."); 195 | continue; 196 | } 197 | 198 | curCost += curCdnNodeIds.size() * g.cdnCost; 199 | if(curCost < lastCost){ 200 | System.out.println("----------------------------------"); 201 | System.out.println("curCost < lastCost: "+curCost +" < "+lastCost); 202 | lastCost = curCost; 203 | lastCdnNodeIds.clear(); 204 | lastCdnNodeIds.addAll(curCdnNodeIds); 205 | System.out.println("更优!!!接受!!!当前cost: "+lastCost ); 206 | System.out.println("当前cdn数目: "+lastCdnNodeIds.size() ); 207 | System.out.println("----------------------------------"); 208 | unacTimes = 0; 209 | break; 210 | } 211 | 212 | metropolis = Math.exp( -(double)(curCost - lastCost) / this.curT); 213 | System.out.println("----------------------------------"); 214 | System.out.println("(double)(curCost - lastCost) :"+(double)(curCost - lastCost) ); 215 | System.out.println("metropolis :"+metropolis ); 216 | if(metropolis >= this.p){ 217 | lastCost = curCost; 218 | lastCdnNodeIds.clear(); 219 | lastCdnNodeIds.addAll(curCdnNodeIds); 220 | System.out.print("只差了一点。接受!!! " ); 221 | System.out.println("当前cost :"+lastCost ); 222 | System.out.println("当前cdn数目: "+lastCdnNodeIds.size() ); 223 | System.out.println("----------------------------------"); 224 | unacTimes = 0; 225 | break; 226 | } 227 | unacTimes ++; 228 | System.out.println("差太多,不接受!!!"+"当前维持cost :"+lastCost );// 229 | System.out.println("当前维持cdn数目: "+lastCdnNodeIds.size() ); 230 | System.out.println("----------------------------------"); 231 | break; 232 | } 233 | } 234 | this.curT *= deCold ; 235 | } 236 | } 237 | 238 | 239 | private void nearSolutionLESS(ArrayList lastCdnNodeIds,ArrayList fixedCdnIds,NetworkGraph g, GraphAlgo graphAlgo,int countForLess,int caseKind){ 240 | 241 | newCdnNodeIds.clear(); 242 | newCdnNodeIds.addAll(lastCdnNodeIds) ; 243 | 244 | int ran,ranSelectedCdnId; 245 | 246 | for(int i = 0; i < countForLess; i++){ 247 | while(true){ 248 | ran = (int)(Math.random() * newCdnNodeIds.size()) ; 249 | ranSelectedCdnId = newCdnNodeIds.get(ran); 250 | if(!fixedCdnIds.contains(ranSelectedCdnId)){ 251 | break; 252 | } 253 | } 254 | newCdnNodeIds.remove(ran); 255 | } 256 | return ; 257 | } 258 | 259 | 260 | private void nearSolutionKeep(ArrayList lastCdnNodeIds,ArrayList fixedCdnIds,NetworkGraph g,int countForKeep){ 261 | 262 | newCdnNodeIds.clear(); 263 | newCdnNodeIds.addAll(lastCdnNodeIds) ; 264 | 265 | int ran,ranSelectedCdnId; 266 | 267 | for(int i = 0; i < countForKeep; i++){ 268 | while(true){ 269 | ran = (int)(Math.random() * newCdnNodeIds.size()) ; 270 | ranSelectedCdnId = newCdnNodeIds.get(ran); 271 | if(fixedCdnIds.contains(ranSelectedCdnId)){ 272 | continue; 273 | } 274 | if(g.getNode(ranSelectedCdnId).userNeighbors.size()<1){ 275 | continue; 276 | } 277 | int ran2 = (int)(Math.random() * g.getNode(ranSelectedCdnId).userNeighbors.size()); 278 | int ranSelectedCdnId2 = g.getNode(ranSelectedCdnId).userNeighbors.get(ran2); 279 | if(newCdnNodeIds.contains(ranSelectedCdnId2)){ 280 | continue; 281 | } 282 | newCdnNodeIds.remove(ran); 283 | newCdnNodeIds.add(ranSelectedCdnId2); 284 | break; 285 | 286 | } 287 | 288 | } 289 | return ; 290 | } 291 | 292 | private void nearSolutionMORE(ArrayList lastCdnNodeIds,ArrayList fixedCdnIds,NetworkGraph g, GraphAlgo graphAlgo,int countForMore){ 293 | 294 | newCdnNodeIds.clear(); 295 | newCdnNodeIds.addAll(lastCdnNodeIds) ; 296 | 297 | int ran; 298 | int ranSelectedCdnId; 299 | for(int i = 0; i < countForMore; i++){ 300 | while(true){ 301 | if(lastCdnNodeIds.size() >= g.users.userList.size()){ 302 | System.out.println("加满了,目前个数:"+lastCdnNodeIds.size()); 303 | return ; 304 | } 305 | ran = (int)(Math.random() * g.users.userList.size()) ; 306 | ranSelectedCdnId = g.users.userList.get(ran).linkedNodeId; 307 | if(newCdnNodeIds.contains(ranSelectedCdnId)){ 308 | continue; 309 | }else{ 310 | newCdnNodeIds.add(ranSelectedCdnId); 311 | break ; 312 | } 313 | } 314 | } 315 | return ; 316 | } 317 | 318 | private void nearSolutionMOREforLow(ArrayList lastCdnNodeIds,ArrayList fixedCdnIds,NetworkGraph g, GraphAlgo graphAlgo,int countForMore){ 319 | 320 | newCdnNodeIds.clear(); 321 | newCdnNodeIds.addAll(lastCdnNodeIds) ; 322 | 323 | int ran; 324 | int ranSelectedCdnId; 325 | for(int i = 0; i < countForMore; i++){ 326 | while(true){ 327 | if(lastCdnNodeIds.size() >= g.nodeNum){ 328 | System.out.println("forLLL加满了,目前个数:"+lastCdnNodeIds.size()); 329 | return ; 330 | } 331 | ran = (int)(Math.random() * g.nodes.size()) ; 332 | ranSelectedCdnId = g.nodes.get(ran).nodeId; 333 | if(ranSelectedCdnId >= g.nodeNum){ 334 | continue; 335 | } 336 | if(newCdnNodeIds.contains(ranSelectedCdnId)){ 337 | continue; 338 | }else{ 339 | newCdnNodeIds.add(ranSelectedCdnId); 340 | break ; 341 | } 342 | } 343 | } 344 | return ; 345 | } 346 | 347 | private void nearSolutionKeepforLow(ArrayList lastCdnNodeIds,ArrayList fixedCdnIds,NetworkGraph g,int countForKeep){ 348 | 349 | newCdnNodeIds.clear(); 350 | newCdnNodeIds.addAll(lastCdnNodeIds) ; 351 | 352 | int ran,ranSelectedCdnId; 353 | 354 | for(int i = 0; i < countForKeep; i++){ 355 | while(true){ 356 | ran = (int)(Math.random() * g.nodes.size()) ; 357 | ranSelectedCdnId = g.nodes.get(ran).nodeId; 358 | if(fixedCdnIds.contains(ranSelectedCdnId) || ranSelectedCdnId>=g.nodeNum || g.getNode(ranSelectedCdnId).neighbors.size()<1){ 359 | continue; 360 | } 361 | 362 | int ran2 = (int)(Math.random() * g.getNode(ranSelectedCdnId).neighbors.size()); 363 | int ranSelectedCdnId2 = g.getNode(ranSelectedCdnId).neighbors.get(ran2); 364 | if(newCdnNodeIds.contains(ranSelectedCdnId2)){ 365 | continue; 366 | } 367 | for(int dn = 0;dn bestPathList; 11 | private int[] aug; 12 | private int[] disTo; 13 | private int[] edgeTo; 14 | LinkedList queue; 15 | private boolean[] onQ; 16 | 17 | public GraphAlgo(int nodeNum) { 18 | aug = new int[nodeNum]; 19 | disTo = new int[nodeNum]; 20 | edgeTo = new int[nodeNum]; 21 | queue = new LinkedList(); 22 | bestPathList = new ArrayList(); 23 | onQ = new boolean[nodeNum]; 24 | } 25 | 26 | public Path SPFA(NetworkGraph g, int startNd, int endNd) { 27 | for(int i = 0; i < disTo.length;i++){ 28 | disTo[i] = Integer.MAX_VALUE; 29 | edgeTo[i] = -1; 30 | aug[i] = 0; 31 | onQ[i]=false; 32 | } 33 | disTo[startNd] = 0; 34 | aug[startNd] = Integer.MAX_VALUE; 35 | queue.clear(); 36 | queue.add(startNd); 37 | onQ[startNd]=true; 38 | while(!queue.isEmpty()) { 39 | int nodeId = queue.getFirst(); 40 | queue.pop(); 41 | for(Integer edgeId : g.getNode(nodeId).getEdgeIds()) { 42 | Edge e = g.getEdge(edgeId); 43 | if(e.capacity > e.flow && disTo[e.endNd] > disTo[nodeId] + e.price) { 44 | disTo[e.endNd] = disTo[nodeId] + e.price; 45 | edgeTo[e.endNd] = edgeId; 46 | aug[e.endNd] = Math.min(aug[nodeId], e.capacity - e.flow); 47 | if(!onQ[e.endNd]) { 48 | if(queue.isEmpty()) { 49 | onQ[e.endNd]=true; 50 | queue.push(e.endNd); 51 | } 52 | else { 53 | if(disTo[e.endNd] >= disTo[queue.getFirst()]) { 54 | onQ[e.endNd]=true; 55 | queue.addLast(e.endNd); 56 | } 57 | else { 58 | onQ[e.endNd]=true; 59 | queue.addFirst(e.endNd); 60 | } 61 | } 62 | } 63 | } 64 | } 65 | onQ[nodeId]=false; 66 | } 67 | 68 | if(disTo[endNd] == Integer.MAX_VALUE) return null; 69 | 70 | LinkedList path = new LinkedList(); 71 | int index = endNd; 72 | while(index != startNd) { 73 | Edge e = g.getEdge(edgeTo[index]); 74 | e.flow += aug[endNd]; 75 | g.getEdge(edgeTo[index]^1).flow -= aug[endNd]; 76 | path.addFirst(edgeTo[index]); 77 | index = e.startNd; 78 | 79 | } 80 | return new Path(aug[endNd], disTo[endNd], path); 81 | } 82 | 83 | 84 | private int MincostMaxflow(NetworkGraph g, int startNd, int endNd, int neededFlow) { 85 | int totalCost = 0; 86 | int countFlow = neededFlow; 87 | Path path; 88 | while((path = SPFA(g, startNd, endNd)) != null) { 89 | countFlow = countFlow - path.flow; 90 | totalCost += path.flow * path.pathCost; 91 | if(countFlow <= 0) { 92 | if(countFlow < 0) { 93 | path.flow = countFlow + path.flow; 94 | for(Integer edgeId:path.path) { 95 | g.getEdge(edgeId).flow += countFlow; 96 | g.getEdge(edgeId^1).flow -= countFlow; 97 | } 98 | totalCost += countFlow * path.pathCost; 99 | } 100 | break; 101 | } 102 | } 103 | if(countFlow > 0) return -1; 104 | 105 | 106 | int curCost = totalCost + g.cdnCost * g.superSource.getEdgeIds().size(); 107 | if(curCost < bestCost) { 108 | ArrayList 109 | pathList = getPathList(g); 110 | GraphAlgo.updateBestRecord(g, pathList, curCost); 111 | } 112 | 113 | return totalCost; 114 | 115 | } 116 | 117 | public int MincostMaxflowForGA(NetworkGraph g, ArrayList nodeIds,Timer t) { 118 | g.addSuperSourceEdges(nodeIds); 119 | int cost = this.MincostMaxflow(g, g.superSourceId, g.superSinkId, g.totalReqBandwidth); 120 | g.cleanSuperSourceEdges(); 121 | g.cleanFlows(); 122 | return cost; 123 | } 124 | 125 | 126 | private static void updateBestRecord(NetworkGraph g, ArrayList pathList, int curCost) { 127 | bestCost = curCost; 128 | bestPathList.clear(); 129 | bestPathList.addAll(pathList); 130 | } 131 | 132 | 133 | private ArrayList getPathList(NetworkGraph g) { 134 | ArrayList pathList = new ArrayList(); 135 | 136 | for(Integer edgeId:g.nodes.get(g.superSourceId).getEdgeIds()) { 137 | StringBuffer pathString = new StringBuffer(); 138 | Edge edge = g.edges.get(edgeId); 139 | pathString.append(edge.endNd); 140 | this.getPathListByDfs(g, edge, edge.flow, pathList, pathString); 141 | } 142 | return pathList; 143 | } 144 | 145 | public int getPathListByDfs(NetworkGraph g, Edge edge, int minFlow, ArrayList pathList, StringBuffer pathString) { 146 | int newMinFlow = Math.min(minFlow, edge.flow); 147 | int tmp = newMinFlow; 148 | if(edge.endNd == g.superSinkId) { 149 | pathString.append(" "); 150 | pathString.append(g.users.nodeToUser.get(edge.startNd)); 151 | pathString.append(" "); 152 | pathString.append(newMinFlow); 153 | pathList.add(pathString.toString()); 154 | edge.flow -= newMinFlow; 155 | return newMinFlow; 156 | } 157 | for(Integer edgeId:g.nodes.get(edge.endNd).getEdgeIds()) { 158 | Edge subEdge = g.edges.get(edgeId); 159 | if(subEdge.price >= 0 && subEdge.flow > 0) { 160 | StringBuffer subPathString = new StringBuffer(pathString.toString()); 161 | if(subEdge.endNd != g.superSinkId) { 162 | subPathString.append(" "); 163 | subPathString.append(subEdge.endNd); 164 | } 165 | int flwCost = getPathListByDfs(g, subEdge, tmp, pathList, subPathString); 166 | tmp -= flwCost; 167 | if(tmp == 0) break; 168 | } 169 | } 170 | edge.flow -= newMinFlow; 171 | return newMinFlow; 172 | } 173 | 174 | // public ArrayList revFlow(NetworkGraph g) { 175 | // ArrayList unCertainUsers = new ArrayList(); 176 | // for(User user : g.users.userList) { 177 | // if(!g.nodes.get(user.linkedNodeId).isRealCDN()) { 178 | // unCertainUsers.add(user.linkedNodeId); 179 | // this.SPFAforRevFlow(g, user); 180 | // } 181 | // } 182 | // return unCertainUsers; 183 | // } 184 | // 185 | // private void SPFAforRevFlow(NetworkGraph g, User user) { 186 | // for(int i = 0; i < marked.length; i++) { 187 | // marked[i] = false; 188 | // } 189 | // queue.clear(); 190 | // queue.add(user.linkedNodeId); 191 | // marked[user.linkedNodeId] = true; 192 | // int step = 0; 193 | // while(!queue.isEmpty()) { 194 | // int nodeId = queue.pop(); 195 | // int edgeLength = g.getNode(nodeId).getEdgeIds().size(); 196 | // for(int i = 0; i < edgeLength; i++) { 197 | // int edgeId = g.getNode(nodeId).getEdgeIds().get(i); 198 | // Edge e = g.getEdge(edgeId); 199 | // if(e.price < 0 || e.capacity < user.reqBandwidth || marked[e.endNd]) continue; 200 | // queue.push(e.endNd); 201 | // marked[e.endNd] = true; 202 | // g.nodes.get(e.endNd).revFlowUsers.add(user.linkedNodeId); 203 | // step++; 204 | // } 205 | // if((step == 0)) { 206 | // step++; 207 | // for(Integer edgeId : g.getNode(nodeId).getEdgeIds()) { 208 | // Edge e = g.getEdge(edgeId); 209 | // if(e.price < 0 || marked[e.endNd]) continue; 210 | // g.nodes.get(e.endNd).revFlowUsers.add(user.linkedNodeId); 211 | // marked[e.endNd] = true; 212 | // } 213 | // } 214 | // } 215 | // } 216 | // public ArrayList preTreatment(NetworkGraph g) { 217 | // ArrayList fixedCDNIds = new ArrayList(); 218 | // for(User user:g.users.userList) { 219 | // if(user.linkedNodeId == 327){ 220 | // System.out.println(327); 221 | // } 222 | // int sumCap = 0; 223 | // for(Integer edgeId:g.nodes.get(user.linkedNodeId).getEdgeIds()) { 224 | // if(g.edges.get(edgeId).price > 0){ 225 | // sumCap += g.edges.get(edgeId).capacity; 226 | // } 227 | // } 228 | // if(sumCap < user.reqBandwidth){ 229 | // g.nodes.get(user.linkedNodeId).setRealCDN(); 230 | // fixedCDNIds.add(user.linkedNodeId); 231 | // } 232 | // } 233 | // return fixedCDNIds; 234 | // } 235 | 236 | 237 | public ArrayList selfishness(NetworkGraph g,int tolerance) { 238 | ArrayList fixedCDNIds = new ArrayList(); 239 | for(User user:g.users.userList) { 240 | TreeMap links = new TreeMap();//key:rent鈥斺��>value:total capacity 241 | for(Integer edgeId:g.nodes.get(user.linkedNodeId).getEdgeIds()) { 242 | if(g.edges.get(edgeId).price > 0){ 243 | if(links.containsKey(g.edges.get(edgeId).price)){ 244 | links.put(g.edges.get(edgeId).price,links.get(g.edges.get(edgeId).price) + g.edges.get(edgeId).capacity); 245 | }else{ 246 | links.put(g.edges.get(edgeId).price, g.edges.get(edgeId).capacity); 247 | } 248 | } 249 | } 250 | int curUserReq = user.reqBandwidth; 251 | int leastCost = 0; 252 | for(Integer rent:links.keySet()){ 253 | curUserReq -= links.get(rent); 254 | leastCost += links.get(rent) * rent; 255 | if(curUserReq == 0) break; 256 | if(curUserReq < 0) { 257 | leastCost -= (-curUserReq) * rent; 258 | break; 259 | } 260 | } 261 | 262 | 263 | 264 | if(leastCost >= g.cdnCost - tolerance){ 265 | g.nodes.get(user.linkedNodeId).setRealCDN(); 266 | fixedCDNIds.add(user.linkedNodeId); 267 | } 268 | } 269 | return fixedCDNIds; 270 | } 271 | 272 | } 273 | 274 | 275 | 276 | 277 | -------------------------------------------------------------------------------- /退火+ SPFA by Java/src/com/LogUtil.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | import java.text.MessageFormat; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Calendar; 6 | import java.util.Date; 7 | 8 | public class LogUtil 9 | { 10 | static class Time 11 | { 12 | private static final long start = System.currentTimeMillis(); 13 | 14 | private long current = 0; 15 | 16 | public Time() 17 | { 18 | } 19 | 20 | public long getTimeDelay() 21 | { 22 | current = System.currentTimeMillis(); 23 | return current - start; 24 | } 25 | 26 | public long getStart() 27 | { 28 | return start; 29 | } 30 | } 31 | 32 | public static void printLog(final String log) 33 | { 34 | 35 | String logtemp = "{0} date/time is: {1} \r\nuse time is {2} s {3} ms."; 36 | 37 | Date date = new Date(); 38 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 39 | String dateString = formatter.format(date); 40 | 41 | Time time = new Time(); 42 | long delay = time.getTimeDelay(); 43 | Calendar calendar = Calendar.getInstance(); 44 | calendar.setTimeInMillis(delay); 45 | 46 | System.err.println(MessageFormat.format(logtemp, new Object[] 47 | {log, dateString, calendar.get(Calendar.SECOND), calendar.get(Calendar.MILLISECOND)})); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /退火+ SPFA by Java/src/com/Main.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | public class Main 4 | { 5 | public static void main(String[] args) 6 | { 7 | if (args.length != 2) 8 | { 9 | System.err.println("please input args: graphFilePath, resultFilePath"); 10 | return; 11 | } 12 | 13 | String graphFilePath = args[0]; 14 | String resultFilePath = args[1]; 15 | 16 | LogUtil.printLog("Begin"); 17 | 18 | // 读取输入文件 19 | String[] graphContent = FileUtil.read(graphFilePath, null); 20 | 21 | // 功能实现入口 22 | String[] resultContents = Deploy.deployServer(graphContent); 23 | 24 | // 写入输出文件 25 | if (hasResults(resultContents)) 26 | { 27 | FileUtil.write(resultFilePath, resultContents, false); 28 | } 29 | else 30 | { 31 | FileUtil.write(resultFilePath, new String[] { "NA" }, false); 32 | } 33 | LogUtil.printLog("End"); 34 | } 35 | 36 | private static boolean hasResults(String[] resultContents) 37 | { 38 | if(resultContents==null) 39 | { 40 | return false; 41 | } 42 | for (String contents : resultContents) 43 | { 44 | if (contents != null && !contents.trim().isEmpty()) 45 | { 46 | return true; 47 | } 48 | } 49 | return false; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /退火+ SPFA by Java/src/com/NetworkGraph.java: -------------------------------------------------------------------------------- 1 | 2 | package com; 3 | 4 | import java.util.ArrayList; 5 | import java.util.Collections; 6 | //import java.util.Comparator; 7 | import java.util.HashMap; 8 | import java.util.HashSet; 9 | import java.util.LinkedList; 10 | 11 | public class NetworkGraph { 12 | public final int nodeNum; 13 | public final int edgeNum; 14 | public ArrayList nodes; 15 | public ArrayList edges; 16 | public int cdnCost; 17 | public Users users; 18 | public int totalReqBandwidth; 19 | public Node superSource; 20 | private Node superSink; 21 | public final int superSourceId; 22 | public final int superSinkId; 23 | 24 | 25 | 26 | public NetworkGraph(int nodeNum, int edgeNum, int userNum) { 27 | this.nodeNum = nodeNum; 28 | this.edgeNum = edgeNum; 29 | nodes = new ArrayList(); 30 | edges = new ArrayList(); 31 | for(int i = 0; i < nodeNum; i++) { 32 | Node node = new Node(i); 33 | nodes.add(node); 34 | } 35 | superSourceId = nodeNum; 36 | superSource = new Node(superSourceId); 37 | nodes.add(superSource); 38 | 39 | superSinkId = nodeNum + 1; 40 | superSink = new Node(superSinkId); 41 | nodes.add(superSink); 42 | 43 | users = new Users(userNum); 44 | totalReqBandwidth = 0; 45 | } 46 | 47 | 48 | public boolean addEdge(int Nd1, int Nd2, int capacity, int price) { 49 | if(Nd1 < 0 || Nd1 >= nodeNum || Nd2 < 0 || Nd2 >= nodeNum) return false; 50 | 51 | // if(!Edge.isLegalCapacity(capacity)) return false; 52 | // if(!Edge.isLegalPrice(price)) return false; 53 | // if(!Edge.isLegalLink(nodes.get(Nd1).getOutDegree(), nodes.get(Nd2).getOutDegree())) return false; 54 | 55 | edges.add(new Edge(Nd1, Nd2, capacity, price)); 56 | edges.add(new Edge(Nd2, Nd1, 0, -price)); 57 | int m = edges.size(); 58 | nodes.get(Nd1).addEdgeId(m - 2); 59 | nodes.get(Nd2).addEdgeId(m - 1); 60 | nodes.get(Nd1).addOutDegree(); 61 | 62 | edges.add(new Edge(Nd2, Nd1, capacity, price)); 63 | edges.add(new Edge(Nd1, Nd2, 0, -price)); 64 | m = edges.size(); 65 | nodes.get(Nd2).addEdgeId(m - 2); 66 | nodes.get(Nd1).addEdgeId(m - 1); 67 | nodes.get(Nd2).addOutDegree(); 68 | 69 | return true; 70 | } 71 | 72 | 73 | // public ArrayList getCandidateNds(int threshold) { 74 | // ArrayList result = new ArrayList(); 75 | // ArrayList potentialCDN = new ArrayList(); 76 | // 77 | // for(Node node: this.nodes) { 78 | // if(node.revFlowUsers.size() >= threshold) { 79 | // result.add(node); 80 | // potentialCDN.add(node.nodeId); 81 | // 82 | // } 83 | // } 84 | // 85 | // Collections.sort(result, new Node.revFlowOrder()); 86 | 87 | // return potentialCDN; 88 | // } 89 | 90 | 91 | public void addSuperSourceEdges(ArrayList targetNds) { 92 | for(Integer targetNd:targetNds) { 93 | edges.add(new Edge(superSourceId, targetNd, Integer.MAX_VALUE, 0)); 94 | edges.add(new Edge(targetNd, superSourceId, 0, 0)); 95 | int m = edges.size(); 96 | superSource.addEdgeId(m - 2); 97 | nodes.get(targetNd).addEdgeId(m - 1); 98 | } 99 | } 100 | 101 | public void cleanSuperSourceEdges() { 102 | for(Integer edgeId:superSource.getEdgeIds()) { 103 | 104 | int nodeId = edges.get(edgeId).endNd; 105 | nodes.get(nodeId).removeEdgeId(edgeId + 1); 106 | } 107 | int edgeId = superSource.getEdgeIds().get(0); 108 | for(int i = edges.size()-1;i >= edgeId;i--){ 109 | edges.remove(i); 110 | } 111 | superSource.cleanEdgeIds(); 112 | } 113 | 114 | public void addSuperSinkEdges() { 115 | for(User user:this.users.userList) { 116 | totalReqBandwidth += user.reqBandwidth; 117 | edges.add(new Edge(user.linkedNodeId, superSinkId, user.reqBandwidth, 0)); 118 | edges.add(new Edge(superSinkId, user.linkedNodeId, 0, 0)); 119 | int m = edges.size(); 120 | nodes.get(user.linkedNodeId).addEdgeId(m - 2); 121 | superSink.addEdgeId(m - 1); 122 | } 123 | } 124 | 125 | public void cleanSuperSinkEdges() { 126 | for(Integer edgeId:superSink.getEdgeIds()) { 127 | nodes.get(edges.get(edgeId).endNd).removeEdgeId(edgeId - 1); 128 | edges.remove(edgeId - 1); 129 | edges.remove(edgeId); 130 | } 131 | superSink.cleanEdgeIds(); 132 | } 133 | 134 | 135 | public Node getNode(int nodeID) { 136 | return this.nodes.get(nodeID); 137 | } 138 | 139 | public Edge getEdge(int edgeId) { 140 | return this.edges.get(edgeId); 141 | } 142 | 143 | public void cleanFlows() { 144 | for(Edge edge: edges) { 145 | edge.cleanFlow(); 146 | } 147 | } 148 | 149 | public void setCDNcost(int cdnCost) { 150 | this.cdnCost = cdnCost; 151 | } 152 | 153 | // public static boolean isLegalNodeNum(int nodeNum) { 154 | // if (nodeNum > 0 && nodeNum <= ConUtil.MAX_NODE_NUM) 155 | // return true; 156 | // return false; 157 | // } 158 | 159 | // public static boolean isLegalCDNCost(int cdnCost) { 160 | // if (cdnCost >= 0 && cdnCost <= ConUtil.MAX_CDN_COST) 161 | // return true; 162 | // return false; 163 | // } 164 | 165 | 166 | public void setAllNeighbors(){ 167 | for(Node node: nodes){ 168 | node.setNeighbors(this.edges,this.users); 169 | } 170 | } 171 | 172 | 173 | public ArrayList getGoodNodes(int threshold){ 174 | ArrayList goodNodes = new ArrayList(); 175 | for(Node node:this.nodes){ 176 | int nodeNeiContain = 0; 177 | for(Integer edgeId:node.getEdgeIds()){ 178 | if(this.edges.get(edgeId).price > 0){ 179 | if(this.users.nodeToUser.keySet().contains(this.edges.get(edgeId).endNd)){ 180 | nodeNeiContain++; 181 | } 182 | } 183 | } 184 | if(nodeNeiContain >= threshold){ 185 | goodNodes.add(node.nodeId); 186 | } 187 | 188 | } 189 | return goodNodes; 190 | 191 | } 192 | 193 | 194 | } 195 | class Edge { 196 | public final int startNd; 197 | public final int endNd; 198 | public final int capacity; 199 | public final int price; 200 | public int flow; 201 | 202 | public Edge(int startNd, int endNd, int capacity, int price) 203 | { 204 | this.startNd = startNd; 205 | this.endNd = endNd; 206 | this.capacity = capacity; 207 | this.price = price; 208 | flow = 0; 209 | } 210 | 211 | public void cleanFlow() { 212 | this.flow = 0; 213 | } 214 | 215 | // static boolean isLegalPrice(int Price) 216 | // { 217 | // if (Price >= 0 && Price <= ConUtil.MAX_PRICE) 218 | // return true; 219 | // return false; 220 | // } 221 | 222 | // static boolean isLegalCapacity(int capacity) 223 | // { 224 | // if (capacity >= 0 && capacity <= ConUtil.MAX_CAPCITY) 225 | // return true; 226 | // return false; 227 | // } 228 | 229 | // static boolean isLegalLink(int startDegree, int endDegree)//閿熸枻鎷疯閿熺潾闈╂嫹 230 | // { 231 | // if(startDegree > ConUtil.MAX_DEGREE_NUM || endDegree > ConUtil.MAX_DEGREE_NUM) 232 | // return false; 233 | // return true; 234 | // } 235 | } 236 | class Node { 237 | public int nodeId; 238 | private int outDegree; 239 | HashSet edgeIds; 240 | private boolean realCDN; 241 | public int userId; 242 | 243 | 244 | public ArrayList revFlowUsers; 245 | 246 | public ArrayList neighbors; 247 | public ArrayList userNeighbors; 248 | 249 | public void setNeighbors(ArrayList edges,Users users){ 250 | for(Integer edgeId:this.edgeIds){ 251 | if(edges.get(edgeId).price > 0){ 252 | this.neighbors.add(edges.get(edgeId).endNd); 253 | if(users.nodeToUser.keySet().contains(edges.get(edgeId).endNd)){ 254 | this.userNeighbors.add(edges.get(edgeId).endNd); 255 | } 256 | } 257 | } 258 | } 259 | 260 | 261 | public Node(int id) { 262 | this.nodeId = id; 263 | edgeIds = new HashSet(); 264 | realCDN = false; 265 | userId = -1; 266 | 267 | revFlowUsers = new ArrayList(); 268 | 269 | 270 | neighbors= new ArrayList(); 271 | userNeighbors = new ArrayList(); 272 | 273 | } 274 | 275 | void setRealCDN() { 276 | this.realCDN = true; 277 | } 278 | 279 | 280 | boolean isRealCDN() { 281 | return realCDN; 282 | } 283 | 284 | void addOutDegree() { 285 | this.outDegree++; 286 | } 287 | 288 | int getOutDegree() { 289 | return this.outDegree; 290 | } 291 | 292 | void addEdgeId(int edgeId) { 293 | this.edgeIds.add(edgeId); 294 | } 295 | 296 | void cleanEdgeIds() { 297 | this.edgeIds.clear(); 298 | } 299 | 300 | ArrayList getEdgeIds() { 301 | ArrayList edgeList = new ArrayList(this.edgeIds); 302 | Collections.sort(edgeList); 303 | return edgeList; 304 | } 305 | 306 | void removeEdgeId(int edgeId) { 307 | this.edgeIds.remove(edgeId); 308 | 309 | } 310 | 311 | 312 | // public static class revFlowOrder implements Comparator{ 313 | // public int compare(Node a,Node b) { 314 | // if(a.revFlowUsers.size() > b.revFlowUsers.size()) return -1; 315 | // if(a.revFlowUsers.size() < b.revFlowUsers.size()) return +1; 316 | // 317 | // return 0; 318 | // } 319 | // } 320 | 321 | public String toString() { 322 | return "nodeId: " + this.nodeId; 323 | } 324 | } 325 | class Path { 326 | public int flow; 327 | public int pathCost; 328 | public LinkedList path; 329 | 330 | public Path(int flow, int pathCost, LinkedList path) { 331 | this.flow = flow; 332 | this.pathCost = pathCost; 333 | this.path = path; 334 | } 335 | 336 | public String toString(NetworkGraph g) { 337 | StringBuffer pathString = new StringBuffer();; 338 | int LastEdge = 0; 339 | for(Integer edgeId:this.path) { 340 | LastEdge = edgeId; 341 | if(g.getEdge(edgeId).endNd == g.nodeNum + 1) break; 342 | pathString.append(g.getEdge(edgeId).endNd + " "); 343 | LastEdge = edgeId; 344 | } 345 | pathString.append(g.users.nodeToUser.get(g.getEdge(LastEdge).startNd)+" "); 346 | pathString.append(this.flow); 347 | return pathString.toString(); 348 | } 349 | } 350 | 351 | class Users { 352 | public final int userNum; 353 | public ArrayList userList; 354 | private boolean[] linkedNodeHash; 355 | public HashMap nodeToUser; 356 | 357 | public Users(int userNum) { 358 | this.userNum = userNum; 359 | userList = new ArrayList(); 360 | linkedNodeHash = new boolean[ConUtil.MAX_NODE_NUM]; 361 | nodeToUser = new HashMap(); 362 | } 363 | 364 | public boolean isLegalLinkedNode(int linkedNodeID) { 365 | if(this.linkedNodeHash[linkedNodeID]) return false; 366 | return true; 367 | } 368 | 369 | public static boolean isLegalUserNum(int userNum) { 370 | if (userNum > 0 && userNum <= ConUtil.MAX_USER_NUM) 371 | return true; 372 | return false; 373 | } 374 | 375 | public void addUser(int id, int linkedNodeID, int reqBandwidth) { 376 | User user = new User(id, linkedNodeID, reqBandwidth); 377 | this.linkedNodeHash[linkedNodeID] = true; 378 | userList.add(user); 379 | nodeToUser.put(linkedNodeID, id); 380 | } 381 | 382 | } 383 | 384 | class User { 385 | public final int id; 386 | public final int linkedNodeId; 387 | public final int reqBandwidth; 388 | 389 | 390 | public User(int id, int linkedNodeID, int reqBandwidth) { 391 | this.id = id; 392 | this.linkedNodeId = linkedNodeID; 393 | this.reqBandwidth = reqBandwidth; 394 | } 395 | 396 | static boolean isLegalReq(int reqBandwidth) { 397 | if (reqBandwidth >= 0 && reqBandwidth <= ConUtil.MAX_REQ) 398 | return true; 399 | return false; 400 | } 401 | } -------------------------------------------------------------------------------- /退火+ SPFA by Java/src/com/Timer.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | public class Timer { 4 | private long startTime; 5 | private long thresholdTime; 6 | private long curDuration; 7 | 8 | public void begin() { 9 | this.startTime = System.currentTimeMillis(); 10 | this.curDuration = 0; 11 | } 12 | 13 | public void print() { 14 | long curDuration = System.currentTimeMillis() - this.startTime; 15 | System.out.println((curDuration) + "ms"); 16 | } 17 | 18 | public long duration() { 19 | return System.currentTimeMillis() - this.startTime; 20 | } 21 | 22 | public void clean() { 23 | this.startTime = 0; 24 | this.thresholdTime = 0; 25 | } 26 | 27 | public void setThreshold(int threshold) { 28 | this.thresholdTime = threshold; 29 | } 30 | 31 | public boolean overtime() { 32 | curDuration = System.currentTimeMillis() - this.startTime; 33 | if(curDuration < this.thresholdTime) { 34 | System.out.print("---------------"); 35 | System.out.print("未超时:"+curDuration+" ms"); 36 | System.out.println("----------------"); 37 | return false; 38 | }else { 39 | System.out.print("-----------------"); 40 | System.out.print("超时:"+ curDuration+" ms"); 41 | System.out.println("---------------------"); 42 | return true; 43 | } 44 | } 45 | 46 | } 47 | --------------------------------------------------------------------------------